mirror of
https://github.com/fluencelabs/tendermint
synced 2025-04-25 06:42:16 +00:00
RPCResponse.Result && EventData are registered interfaces; -skip_upnp option
This commit is contained in:
parent
65d40a2d08
commit
1b9fd811a1
@ -9,6 +9,7 @@ import (
|
|||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
"github.com/tendermint/tendermint/rpc/client"
|
"github.com/tendermint/tendermint/rpc/client"
|
||||||
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||||
|
cclient "github.com/tendermint/tendermint/rpc/core_client"
|
||||||
"github.com/tendermint/tendermint/types"
|
"github.com/tendermint/tendermint/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -75,7 +76,7 @@ func main() {
|
|||||||
sendTx := makeRandomTransaction(10, rootAccount.Sequence+1, root, 2, accounts)
|
sendTx := makeRandomTransaction(10, rootAccount.Sequence+1, root, 2, accounts)
|
||||||
fmt.Println(sendTx)
|
fmt.Println(sendTx)
|
||||||
|
|
||||||
wsClient := rpcclient.NewWSClient("ws://" + remote + "/websocket")
|
wsClient := cclient.NewWSClient("ws://" + remote + "/websocket")
|
||||||
_, err = wsClient.Start()
|
_, err = wsClient.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Exit(Fmt("Failed to establish websocket connection: %v", err))
|
Exit(Fmt("Failed to establish websocket connection: %v", err))
|
||||||
|
@ -3,13 +3,13 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/tendermint/tendermint/types"
|
||||||
"github.com/tendermint/tendermint/wire"
|
"github.com/tendermint/tendermint/wire"
|
||||||
sm "github.com/tendermint/tendermint/state"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func gen_validator() {
|
func gen_validator() {
|
||||||
|
|
||||||
privValidator := sm.GenPrivValidator()
|
privValidator := types.GenPrivValidator()
|
||||||
privValidatorJSONBytes := wire.JSONBytes(privValidator)
|
privValidatorJSONBytes := wire.JSONBytes(privValidator)
|
||||||
fmt.Printf(`Generated a new validator!
|
fmt.Printf(`Generated a new validator!
|
||||||
Paste the following JSON into your %v file
|
Paste the following JSON into your %v file
|
||||||
|
@ -3,24 +3,24 @@ package main
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
sm "github.com/tendermint/tendermint/state"
|
"github.com/tendermint/tendermint/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NOTE: this is totally unsafe.
|
// NOTE: this is totally unsafe.
|
||||||
// it's only suitable for testnets.
|
// it's only suitable for testnets.
|
||||||
func reset_priv_validator() {
|
func reset_priv_validator() {
|
||||||
// Get PrivValidator
|
// Get PrivValidator
|
||||||
var privValidator *sm.PrivValidator
|
var privValidator *types.PrivValidator
|
||||||
privValidatorFile := config.GetString("priv_validator_file")
|
privValidatorFile := config.GetString("priv_validator_file")
|
||||||
if _, err := os.Stat(privValidatorFile); err == nil {
|
if _, err := os.Stat(privValidatorFile); err == nil {
|
||||||
privValidator = sm.LoadPrivValidator(privValidatorFile)
|
privValidator = types.LoadPrivValidator(privValidatorFile)
|
||||||
privValidator.LastHeight = 0
|
privValidator.LastHeight = 0
|
||||||
privValidator.LastRound = 0
|
privValidator.LastRound = 0
|
||||||
privValidator.LastStep = 0
|
privValidator.LastStep = 0
|
||||||
privValidator.Save()
|
privValidator.Save()
|
||||||
log.Notice("Reset PrivValidator", "file", privValidatorFile)
|
log.Notice("Reset PrivValidator", "file", privValidatorFile)
|
||||||
} else {
|
} else {
|
||||||
privValidator = sm.GenPrivValidator()
|
privValidator = types.GenPrivValidator()
|
||||||
privValidator.SetFile(privValidatorFile)
|
privValidator.SetFile(privValidatorFile)
|
||||||
privValidator.Save()
|
privValidator.Save()
|
||||||
log.Notice("Generated PrivValidator", "file", privValidatorFile)
|
log.Notice("Generated PrivValidator", "file", privValidatorFile)
|
||||||
|
@ -198,3 +198,11 @@ func (af *AutoFile) openFile() error {
|
|||||||
af.file = file
|
af.file = file
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Tempfile(prefix string) (*os.File, string) {
|
||||||
|
file, err := ioutil.TempFile("", prefix)
|
||||||
|
if err != nil {
|
||||||
|
PanicCrisis(err)
|
||||||
|
}
|
||||||
|
return file, file.Name()
|
||||||
|
}
|
||||||
|
@ -67,6 +67,7 @@ func GetConfig(rootDir string) cfg.Config {
|
|||||||
mapConfig.SetDefault("node_laddr", "0.0.0.0:46656")
|
mapConfig.SetDefault("node_laddr", "0.0.0.0:46656")
|
||||||
// mapConfig.SetDefault("seeds", "goldenalchemist.chaintest.net:46656")
|
// mapConfig.SetDefault("seeds", "goldenalchemist.chaintest.net:46656")
|
||||||
mapConfig.SetDefault("fast_sync", true)
|
mapConfig.SetDefault("fast_sync", true)
|
||||||
|
mapConfig.SetDefault("skip_upnp", false)
|
||||||
mapConfig.SetDefault("addrbook_file", rootDir+"/addrbook.json")
|
mapConfig.SetDefault("addrbook_file", rootDir+"/addrbook.json")
|
||||||
mapConfig.SetDefault("priv_validator_file", rootDir+"/priv_validator.json")
|
mapConfig.SetDefault("priv_validator_file", rootDir+"/priv_validator.json")
|
||||||
mapConfig.SetDefault("db_backend", "leveldb")
|
mapConfig.SetDefault("db_backend", "leveldb")
|
||||||
|
@ -68,6 +68,7 @@ func GetConfig(rootDir string) cfg.Config {
|
|||||||
mapConfig.SetDefault("moniker", "anonymous")
|
mapConfig.SetDefault("moniker", "anonymous")
|
||||||
mapConfig.SetDefault("node_laddr", "0.0.0.0:36656")
|
mapConfig.SetDefault("node_laddr", "0.0.0.0:36656")
|
||||||
mapConfig.SetDefault("fast_sync", false)
|
mapConfig.SetDefault("fast_sync", false)
|
||||||
|
mapConfig.SetDefault("skip_upnp", true)
|
||||||
mapConfig.SetDefault("addrbook_file", rootDir+"/addrbook.json")
|
mapConfig.SetDefault("addrbook_file", rootDir+"/addrbook.json")
|
||||||
mapConfig.SetDefault("priv_validator_file", rootDir+"/priv_validator.json")
|
mapConfig.SetDefault("priv_validator_file", rootDir+"/priv_validator.json")
|
||||||
mapConfig.SetDefault("db_backend", "memdb")
|
mapConfig.SetDefault("db_backend", "memdb")
|
||||||
|
@ -5,13 +5,12 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
sm "github.com/tendermint/tendermint/state"
|
|
||||||
"github.com/tendermint/tendermint/types"
|
"github.com/tendermint/tendermint/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RoundVoteSet struct {
|
type RoundVoteSet struct {
|
||||||
Prevotes *VoteSet
|
Prevotes *types.VoteSet
|
||||||
Precommits *VoteSet
|
Precommits *types.VoteSet
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -28,7 +27,7 @@ peer to prevent abuse.
|
|||||||
*/
|
*/
|
||||||
type HeightVoteSet struct {
|
type HeightVoteSet struct {
|
||||||
height int
|
height int
|
||||||
valSet *sm.ValidatorSet
|
valSet *types.ValidatorSet
|
||||||
|
|
||||||
mtx sync.Mutex
|
mtx sync.Mutex
|
||||||
round int // max tracked round
|
round int // max tracked round
|
||||||
@ -36,7 +35,7 @@ type HeightVoteSet struct {
|
|||||||
peerCatchupRounds map[string]int // keys: peer.Key; values: round
|
peerCatchupRounds map[string]int // keys: peer.Key; values: round
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHeightVoteSet(height int, valSet *sm.ValidatorSet) *HeightVoteSet {
|
func NewHeightVoteSet(height int, valSet *types.ValidatorSet) *HeightVoteSet {
|
||||||
hvs := &HeightVoteSet{
|
hvs := &HeightVoteSet{
|
||||||
height: height,
|
height: height,
|
||||||
valSet: valSet,
|
valSet: valSet,
|
||||||
@ -79,8 +78,8 @@ func (hvs *HeightVoteSet) addRound(round int) {
|
|||||||
PanicSanity("addRound() for an existing round")
|
PanicSanity("addRound() for an existing round")
|
||||||
}
|
}
|
||||||
log.Info("addRound(round)", "round", round)
|
log.Info("addRound(round)", "round", round)
|
||||||
prevotes := NewVoteSet(hvs.height, round, types.VoteTypePrevote, hvs.valSet)
|
prevotes := types.NewVoteSet(hvs.height, round, types.VoteTypePrevote, hvs.valSet)
|
||||||
precommits := NewVoteSet(hvs.height, round, types.VoteTypePrecommit, hvs.valSet)
|
precommits := types.NewVoteSet(hvs.height, round, types.VoteTypePrecommit, hvs.valSet)
|
||||||
hvs.roundVoteSets[round] = RoundVoteSet{
|
hvs.roundVoteSets[round] = RoundVoteSet{
|
||||||
Prevotes: prevotes,
|
Prevotes: prevotes,
|
||||||
Precommits: precommits,
|
Precommits: precommits,
|
||||||
@ -109,13 +108,13 @@ func (hvs *HeightVoteSet) AddByAddress(address []byte, vote *types.Vote, peerKey
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hvs *HeightVoteSet) Prevotes(round int) *VoteSet {
|
func (hvs *HeightVoteSet) Prevotes(round int) *types.VoteSet {
|
||||||
hvs.mtx.Lock()
|
hvs.mtx.Lock()
|
||||||
defer hvs.mtx.Unlock()
|
defer hvs.mtx.Unlock()
|
||||||
return hvs.getVoteSet(round, types.VoteTypePrevote)
|
return hvs.getVoteSet(round, types.VoteTypePrevote)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hvs *HeightVoteSet) Precommits(round int) *VoteSet {
|
func (hvs *HeightVoteSet) Precommits(round int) *types.VoteSet {
|
||||||
hvs.mtx.Lock()
|
hvs.mtx.Lock()
|
||||||
defer hvs.mtx.Unlock()
|
defer hvs.mtx.Unlock()
|
||||||
return hvs.getVoteSet(round, types.VoteTypePrecommit)
|
return hvs.getVoteSet(round, types.VoteTypePrecommit)
|
||||||
@ -134,7 +133,7 @@ func (hvs *HeightVoteSet) POLRound() int {
|
|||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hvs *HeightVoteSet) getVoteSet(round int, type_ byte) *VoteSet {
|
func (hvs *HeightVoteSet) getVoteSet(round int, type_ byte) *types.VoteSet {
|
||||||
log.Info("getVoteSet(round)", "round", round, "type", type_)
|
log.Info("getVoteSet(round)", "round", round, "type", type_)
|
||||||
rvs, ok := hvs.roundVoteSets[round]
|
rvs, ok := hvs.roundVoteSets[round]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -10,7 +10,6 @@ import (
|
|||||||
|
|
||||||
bc "github.com/tendermint/tendermint/blockchain"
|
bc "github.com/tendermint/tendermint/blockchain"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
. "github.com/tendermint/tendermint/consensus/types"
|
|
||||||
"github.com/tendermint/tendermint/events"
|
"github.com/tendermint/tendermint/events"
|
||||||
"github.com/tendermint/tendermint/p2p"
|
"github.com/tendermint/tendermint/p2p"
|
||||||
sm "github.com/tendermint/tendermint/state"
|
sm "github.com/tendermint/tendermint/state"
|
||||||
@ -187,7 +186,7 @@ func (conR *ConsensusReactor) Receive(chId byte, peer *p2p.Peer, msgBytes []byte
|
|||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
case *VoteMessage:
|
case *VoteMessage:
|
||||||
vote := msg.Vote
|
vote := msg.Vote
|
||||||
var validators *sm.ValidatorSet
|
var validators *types.ValidatorSet
|
||||||
if rs.Height == vote.Height {
|
if rs.Height == vote.Height {
|
||||||
validators = rs.Validators
|
validators = rs.Validators
|
||||||
} else if rs.Height == vote.Height+1 {
|
} else if rs.Height == vote.Height+1 {
|
||||||
@ -268,7 +267,7 @@ func (conR *ConsensusReactor) broadcastHasVoteMessage(vote *types.Vote, index in
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sets our private validator account for signing votes.
|
// Sets our private validator account for signing votes.
|
||||||
func (conR *ConsensusReactor) SetPrivValidator(priv *sm.PrivValidator) {
|
func (conR *ConsensusReactor) SetPrivValidator(priv *types.PrivValidator) {
|
||||||
conR.conS.SetPrivValidator(priv)
|
conR.conS.SetPrivValidator(priv)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -598,7 +597,7 @@ func (ps *PeerState) GetRoundState() *PeerRoundState {
|
|||||||
return &prs
|
return &prs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ps *PeerState) SetHasProposal(proposal *Proposal) {
|
func (ps *PeerState) SetHasProposal(proposal *types.Proposal) {
|
||||||
ps.mtx.Lock()
|
ps.mtx.Lock()
|
||||||
defer ps.mtx.Unlock()
|
defer ps.mtx.Unlock()
|
||||||
|
|
||||||
@ -964,7 +963,7 @@ func (m *CommitStepMessage) String() string {
|
|||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
|
|
||||||
type ProposalMessage struct {
|
type ProposalMessage struct {
|
||||||
Proposal *Proposal
|
Proposal *types.Proposal
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ProposalMessage) String() string {
|
func (m *ProposalMessage) String() string {
|
||||||
|
@ -160,7 +160,6 @@ import (
|
|||||||
acm "github.com/tendermint/tendermint/account"
|
acm "github.com/tendermint/tendermint/account"
|
||||||
bc "github.com/tendermint/tendermint/blockchain"
|
bc "github.com/tendermint/tendermint/blockchain"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
. "github.com/tendermint/tendermint/consensus/types"
|
|
||||||
"github.com/tendermint/tendermint/events"
|
"github.com/tendermint/tendermint/events"
|
||||||
mempl "github.com/tendermint/tendermint/mempool"
|
mempl "github.com/tendermint/tendermint/mempool"
|
||||||
sm "github.com/tendermint/tendermint/state"
|
sm "github.com/tendermint/tendermint/state"
|
||||||
@ -231,16 +230,16 @@ type RoundState struct {
|
|||||||
Step RoundStepType
|
Step RoundStepType
|
||||||
StartTime time.Time
|
StartTime time.Time
|
||||||
CommitTime time.Time // Subjective time when +2/3 precommits for Block at Round were found
|
CommitTime time.Time // Subjective time when +2/3 precommits for Block at Round were found
|
||||||
Validators *sm.ValidatorSet
|
Validators *types.ValidatorSet
|
||||||
Proposal *Proposal
|
Proposal *types.Proposal
|
||||||
ProposalBlock *types.Block
|
ProposalBlock *types.Block
|
||||||
ProposalBlockParts *types.PartSet
|
ProposalBlockParts *types.PartSet
|
||||||
LockedRound int
|
LockedRound int
|
||||||
LockedBlock *types.Block
|
LockedBlock *types.Block
|
||||||
LockedBlockParts *types.PartSet
|
LockedBlockParts *types.PartSet
|
||||||
Votes *HeightVoteSet
|
Votes *HeightVoteSet
|
||||||
LastCommit *VoteSet // Last precommits at Height-1
|
LastCommit *types.VoteSet // Last precommits at Height-1
|
||||||
LastValidators *sm.ValidatorSet
|
LastValidators *types.ValidatorSet
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rs *RoundState) String() string {
|
func (rs *RoundState) String() string {
|
||||||
@ -288,7 +287,7 @@ type ConsensusState struct {
|
|||||||
|
|
||||||
blockStore *bc.BlockStore
|
blockStore *bc.BlockStore
|
||||||
mempoolReactor *mempl.MempoolReactor
|
mempoolReactor *mempl.MempoolReactor
|
||||||
privValidator *sm.PrivValidator
|
privValidator *types.PrivValidator
|
||||||
newStepCh chan *RoundState
|
newStepCh chan *RoundState
|
||||||
|
|
||||||
mtx sync.Mutex
|
mtx sync.Mutex
|
||||||
@ -322,7 +321,7 @@ func (cs *ConsensusState) reconstructLastCommit(state *sm.State) {
|
|||||||
if state.LastBlockHeight == 0 {
|
if state.LastBlockHeight == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
lastPrecommits := NewVoteSet(state.LastBlockHeight, 0, types.VoteTypePrecommit, state.LastBondedValidators)
|
lastPrecommits := types.NewVoteSet(state.LastBlockHeight, 0, types.VoteTypePrecommit, state.LastBondedValidators)
|
||||||
seenValidation := cs.blockStore.LoadSeenValidation(state.LastBlockHeight)
|
seenValidation := cs.blockStore.LoadSeenValidation(state.LastBlockHeight)
|
||||||
for idx, precommit := range seenValidation.Precommits {
|
for idx, precommit := range seenValidation.Precommits {
|
||||||
if precommit == nil {
|
if precommit == nil {
|
||||||
@ -408,7 +407,7 @@ func (cs *ConsensusState) updateToState(state *sm.State, contiguous bool) {
|
|||||||
// Reset fields based on state.
|
// Reset fields based on state.
|
||||||
validators := state.BondedValidators
|
validators := state.BondedValidators
|
||||||
height := state.LastBlockHeight + 1 // next desired block height
|
height := state.LastBlockHeight + 1 // next desired block height
|
||||||
lastPrecommits := (*VoteSet)(nil)
|
lastPrecommits := (*types.VoteSet)(nil)
|
||||||
if contiguous && cs.Votes != nil {
|
if contiguous && cs.Votes != nil {
|
||||||
if !cs.Votes.Precommits(cs.Round).HasTwoThirdsMajority() {
|
if !cs.Votes.Precommits(cs.Round).HasTwoThirdsMajority() {
|
||||||
PanicSanity("updateToState(state, true) called but last Precommit round didn't have +2/3")
|
PanicSanity("updateToState(state, true) called but last Precommit round didn't have +2/3")
|
||||||
@ -474,7 +473,7 @@ func (cs *ConsensusState) maybeRebond() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *ConsensusState) SetPrivValidator(priv *sm.PrivValidator) {
|
func (cs *ConsensusState) SetPrivValidator(priv *types.PrivValidator) {
|
||||||
cs.mtx.Lock()
|
cs.mtx.Lock()
|
||||||
defer cs.mtx.Unlock()
|
defer cs.mtx.Unlock()
|
||||||
cs.privValidator = priv
|
cs.privValidator = priv
|
||||||
@ -580,7 +579,7 @@ func (cs *ConsensusState) decideProposal(height int, round int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make proposal
|
// Make proposal
|
||||||
proposal := NewProposal(height, round, blockParts.Header(), cs.Votes.POLRound())
|
proposal := types.NewProposal(height, round, blockParts.Header(), cs.Votes.POLRound())
|
||||||
err := cs.privValidator.SignProposal(cs.state.ChainID, proposal)
|
err := cs.privValidator.SignProposal(cs.state.ChainID, proposal)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
log.Notice("Signed and set proposal", "height", height, "round", round, "proposal", proposal)
|
log.Notice("Signed and set proposal", "height", height, "round", round, "proposal", proposal)
|
||||||
@ -971,7 +970,7 @@ func (cs *ConsensusState) FinalizeCommit(height int) {
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
func (cs *ConsensusState) SetProposal(proposal *Proposal) error {
|
func (cs *ConsensusState) SetProposal(proposal *types.Proposal) error {
|
||||||
cs.mtx.Lock()
|
cs.mtx.Lock()
|
||||||
defer cs.mtx.Unlock()
|
defer cs.mtx.Unlock()
|
||||||
|
|
||||||
@ -1191,7 +1190,7 @@ func (cs *ConsensusState) signAddVote(type_ byte, hash []byte, header types.Part
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Save Block, save the +2/3 Commits we've seen
|
// Save Block, save the +2/3 Commits we've seen
|
||||||
func (cs *ConsensusState) saveBlock(block *types.Block, blockParts *types.PartSet, commits *VoteSet) {
|
func (cs *ConsensusState) saveBlock(block *types.Block, blockParts *types.PartSet, commits *types.VoteSet) {
|
||||||
|
|
||||||
// The proposal must be valid.
|
// The proposal must be valid.
|
||||||
if err := cs.stageBlock(block, blockParts); err != nil {
|
if err := cs.stageBlock(block, blockParts); err != nil {
|
||||||
@ -1212,7 +1211,7 @@ func (cs *ConsensusState) saveBlock(block *types.Block, blockParts *types.PartSe
|
|||||||
|
|
||||||
// Fire off event
|
// Fire off event
|
||||||
go func(block *types.Block) {
|
go func(block *types.Block) {
|
||||||
cs.evsw.FireEvent(types.EventStringNewBlock(), block)
|
cs.evsw.FireEvent(types.EventStringNewBlock(), types.EventDataNewBlock{block})
|
||||||
cs.evc.Flush()
|
cs.evc.Flush()
|
||||||
}(block)
|
}(block)
|
||||||
|
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
package consensus
|
package consensus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sort"
|
|
||||||
|
|
||||||
bc "github.com/tendermint/tendermint/blockchain"
|
bc "github.com/tendermint/tendermint/blockchain"
|
||||||
dbm "github.com/tendermint/tendermint/db"
|
dbm "github.com/tendermint/tendermint/db"
|
||||||
mempl "github.com/tendermint/tendermint/mempool"
|
mempl "github.com/tendermint/tendermint/mempool"
|
||||||
sm "github.com/tendermint/tendermint/state"
|
sm "github.com/tendermint/tendermint/state"
|
||||||
|
"github.com/tendermint/tendermint/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func randConsensusState() (*ConsensusState, []*sm.PrivValidator) {
|
func randConsensusState() (*ConsensusState, []*types.PrivValidator) {
|
||||||
state, _, privValidators := sm.RandGenesisState(20, false, 1000, 10, false, 1000)
|
state, _, privValidators := sm.RandGenesisState(20, false, 1000, 10, false, 1000)
|
||||||
blockStore := bc.NewBlockStore(dbm.NewMemDB())
|
blockStore := bc.NewBlockStore(dbm.NewMemDB())
|
||||||
mempool := mempl.NewMempool(state)
|
mempool := mempl.NewMempool(state)
|
||||||
@ -17,16 +16,3 @@ func randConsensusState() (*ConsensusState, []*sm.PrivValidator) {
|
|||||||
cs := NewConsensusState(state, blockStore, mempoolReactor)
|
cs := NewConsensusState(state, blockStore, mempoolReactor)
|
||||||
return cs, privValidators
|
return cs, privValidators
|
||||||
}
|
}
|
||||||
|
|
||||||
func randVoteSet(height int, round int, type_ byte, numValidators int, votingPower int64) (*VoteSet, *sm.ValidatorSet, []*sm.PrivValidator) {
|
|
||||||
vals := make([]*sm.Validator, numValidators)
|
|
||||||
privValidators := make([]*sm.PrivValidator, numValidators)
|
|
||||||
for i := 0; i < numValidators; i++ {
|
|
||||||
_, val, privValidator := sm.RandValidator(false, votingPower)
|
|
||||||
vals[i] = val
|
|
||||||
privValidators[i] = privValidator
|
|
||||||
}
|
|
||||||
valSet := sm.NewValidatorSet(vals)
|
|
||||||
sort.Sort(sm.PrivValidatorsByAddress(privValidators))
|
|
||||||
return NewVoteSet(height, round, type_, valSet), valSet, privValidators
|
|
||||||
}
|
|
||||||
|
@ -5,12 +5,9 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
"github.com/tendermint/tendermint/rpc/client"
|
|
||||||
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||||
core "github.com/tendermint/tendermint/rpc/core_client"
|
cclient "github.com/tendermint/tendermint/rpc/core_client"
|
||||||
"github.com/tendermint/tendermint/rpc/types"
|
|
||||||
"github.com/tendermint/tendermint/types"
|
"github.com/tendermint/tendermint/types"
|
||||||
"github.com/tendermint/tendermint/wire"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -37,7 +34,7 @@ type Node struct {
|
|||||||
ChainID string
|
ChainID string
|
||||||
BlockHeight int
|
BlockHeight int
|
||||||
BlockHistory map[int]time.Time // when we saw each block
|
BlockHistory map[int]time.Time // when we saw each block
|
||||||
NetInfo *ctypes.ResponseNetInfo
|
NetInfo *ctypes.ResultNetInfo
|
||||||
|
|
||||||
Validator bool
|
Validator bool
|
||||||
|
|
||||||
@ -50,7 +47,7 @@ func (n *Node) Address() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set the basic status and chain_id info for a node from RPC responses
|
// Set the basic status and chain_id info for a node from RPC responses
|
||||||
func (n *Node) SetInfo(status *ctypes.ResponseStatus, netinfo *ctypes.ResponseNetInfo) {
|
func (n *Node) SetInfo(status *ctypes.ResultStatus, netinfo *ctypes.ResultNetInfo) {
|
||||||
n.LastSeen = time.Now()
|
n.LastSeen = time.Now()
|
||||||
n.ChainID = status.NodeInfo.ChainID
|
n.ChainID = status.NodeInfo.ChainID
|
||||||
n.BlockHeight = status.LatestBlockHeight
|
n.BlockHeight = status.LatestBlockHeight
|
||||||
@ -60,15 +57,15 @@ func (n *Node) SetInfo(status *ctypes.ResponseStatus, netinfo *ctypes.ResponseNe
|
|||||||
|
|
||||||
// A node client is used to talk to a node over rpc and websockets
|
// A node client is used to talk to a node over rpc and websockets
|
||||||
type NodeClient struct {
|
type NodeClient struct {
|
||||||
rpc core.Client
|
rpc cclient.Client
|
||||||
ws *rpcclient.WSClient
|
ws *cclient.WSClient
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new client for the node at the given addr
|
// Create a new client for the node at the given addr
|
||||||
func NewNodeClient(addr string) *NodeClient {
|
func NewNodeClient(addr string) *NodeClient {
|
||||||
return &NodeClient{
|
return &NodeClient{
|
||||||
rpc: core.NewClient("http://"+addr, "JSONRPC"),
|
rpc: cclient.NewClient("http://"+addr, "JSONRPC"),
|
||||||
ws: rpcclient.NewWSClient("ws://" + addr + "/events"),
|
ws: cclient.NewWSClient("ws://" + addr + "/events"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,11 +180,8 @@ func (c *Crawler) readLoop(node *Node) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Crawler) consumeMessage(eventMsg rpctypes.RPCEventResult, node *Node) error {
|
func (c *Crawler) consumeMessage(eventMsg ctypes.ResultEvent, node *Node) error {
|
||||||
var block *types.Block
|
block := eventMsg.Data.(*types.Block)
|
||||||
var err error
|
|
||||||
wire.ReadJSONObject(block, eventMsg.Data, &err)
|
|
||||||
|
|
||||||
node.LastSeen = time.Now()
|
node.LastSeen = time.Now()
|
||||||
node.BlockHeight = block.Height
|
node.BlockHeight = block.Height
|
||||||
node.BlockHistory[block.Height] = node.LastSeen
|
node.BlockHistory[block.Height] = node.LastSeen
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
package events
|
package events
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/tendermint/tendermint/types"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
eventsBufferSize = 1000
|
eventsBufferSize = 1000
|
||||||
)
|
)
|
||||||
@ -22,20 +26,20 @@ func NewEventCache(evsw Fireable) *EventCache {
|
|||||||
// a cached event
|
// a cached event
|
||||||
type eventInfo struct {
|
type eventInfo struct {
|
||||||
event string
|
event string
|
||||||
msg interface{}
|
data types.EventData
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache an event to be fired upon finality.
|
// Cache an event to be fired upon finality.
|
||||||
func (evc *EventCache) FireEvent(event string, msg interface{}) {
|
func (evc *EventCache) FireEvent(event string, data interface{}) {
|
||||||
// append to list
|
// append to list
|
||||||
evc.events = append(evc.events, eventInfo{event, msg})
|
evc.events = append(evc.events, eventInfo{event, data})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fire events by running evsw.FireEvent on all cached events. Blocks.
|
// Fire events by running evsw.FireEvent on all cached events. Blocks.
|
||||||
// Clears cached events
|
// Clears cached events
|
||||||
func (evc *EventCache) Flush() {
|
func (evc *EventCache) Flush() {
|
||||||
for _, ei := range evc.events {
|
for _, ei := range evc.events {
|
||||||
evc.evsw.FireEvent(ei.event, ei.msg)
|
evc.evsw.FireEvent(ei.event, ei.data)
|
||||||
}
|
}
|
||||||
evc.events = make([]eventInfo, eventsBufferSize)
|
evc.events = make([]eventInfo, eventsBufferSize)
|
||||||
}
|
}
|
||||||
|
19
node/node.go
19
node/node.go
@ -21,6 +21,7 @@ import (
|
|||||||
"github.com/tendermint/tendermint/rpc/core"
|
"github.com/tendermint/tendermint/rpc/core"
|
||||||
"github.com/tendermint/tendermint/rpc/server"
|
"github.com/tendermint/tendermint/rpc/server"
|
||||||
sm "github.com/tendermint/tendermint/state"
|
sm "github.com/tendermint/tendermint/state"
|
||||||
|
stypes "github.com/tendermint/tendermint/state/types"
|
||||||
"github.com/tendermint/tendermint/types"
|
"github.com/tendermint/tendermint/types"
|
||||||
"github.com/tendermint/tendermint/wire"
|
"github.com/tendermint/tendermint/wire"
|
||||||
)
|
)
|
||||||
@ -37,8 +38,8 @@ type Node struct {
|
|||||||
mempoolReactor *mempl.MempoolReactor
|
mempoolReactor *mempl.MempoolReactor
|
||||||
consensusState *consensus.ConsensusState
|
consensusState *consensus.ConsensusState
|
||||||
consensusReactor *consensus.ConsensusReactor
|
consensusReactor *consensus.ConsensusReactor
|
||||||
privValidator *sm.PrivValidator
|
privValidator *types.PrivValidator
|
||||||
genDoc *sm.GenesisDoc
|
genDoc *stypes.GenesisDoc
|
||||||
privKey acm.PrivKeyEd25519
|
privKey acm.PrivKeyEd25519
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,19 +51,19 @@ func NewNode() *Node {
|
|||||||
// Get State
|
// Get State
|
||||||
stateDB := dbm.GetDB("state")
|
stateDB := dbm.GetDB("state")
|
||||||
state := sm.LoadState(stateDB)
|
state := sm.LoadState(stateDB)
|
||||||
var genDoc *sm.GenesisDoc
|
var genDoc *stypes.GenesisDoc
|
||||||
if state == nil {
|
if state == nil {
|
||||||
genDoc, state = sm.MakeGenesisStateFromFile(stateDB, config.GetString("genesis_file"))
|
genDoc, state = sm.MakeGenesisStateFromFile(stateDB, config.GetString("genesis_file"))
|
||||||
state.Save()
|
state.Save()
|
||||||
// write the gendoc to db
|
// write the gendoc to db
|
||||||
buf, n, err := new(bytes.Buffer), new(int64), new(error)
|
buf, n, err := new(bytes.Buffer), new(int64), new(error)
|
||||||
wire.WriteJSON(genDoc, buf, n, err)
|
wire.WriteJSON(genDoc, buf, n, err)
|
||||||
stateDB.Set(sm.GenDocKey, buf.Bytes())
|
stateDB.Set(stypes.GenDocKey, buf.Bytes())
|
||||||
if *err != nil {
|
if *err != nil {
|
||||||
Exit(Fmt("Unable to write gendoc to db: %v", err))
|
Exit(Fmt("Unable to write gendoc to db: %v", err))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
genDocBytes := stateDB.Get(sm.GenDocKey)
|
genDocBytes := stateDB.Get(stypes.GenDocKey)
|
||||||
err := new(error)
|
err := new(error)
|
||||||
wire.ReadJSONPtr(&genDoc, genDocBytes, err)
|
wire.ReadJSONPtr(&genDoc, genDocBytes, err)
|
||||||
if *err != nil {
|
if *err != nil {
|
||||||
@ -73,14 +74,14 @@ func NewNode() *Node {
|
|||||||
config.Set("chain_id", state.ChainID)
|
config.Set("chain_id", state.ChainID)
|
||||||
|
|
||||||
// Get PrivValidator
|
// Get PrivValidator
|
||||||
var privValidator *sm.PrivValidator
|
var privValidator *types.PrivValidator
|
||||||
privValidatorFile := config.GetString("priv_validator_file")
|
privValidatorFile := config.GetString("priv_validator_file")
|
||||||
if _, err := os.Stat(privValidatorFile); err == nil {
|
if _, err := os.Stat(privValidatorFile); err == nil {
|
||||||
privValidator = sm.LoadPrivValidator(privValidatorFile)
|
privValidator = types.LoadPrivValidator(privValidatorFile)
|
||||||
log.Notice("Loaded PrivValidator",
|
log.Notice("Loaded PrivValidator",
|
||||||
"file", privValidatorFile, "privValidator", privValidator)
|
"file", privValidatorFile, "privValidator", privValidator)
|
||||||
} else {
|
} else {
|
||||||
privValidator = sm.GenPrivValidator()
|
privValidator = types.GenPrivValidator()
|
||||||
privValidator.SetFile(privValidatorFile)
|
privValidator.SetFile(privValidatorFile)
|
||||||
privValidator.Save()
|
privValidator.Save()
|
||||||
log.Notice("Generated PrivValidator", "file", privValidatorFile)
|
log.Notice("Generated PrivValidator", "file", privValidatorFile)
|
||||||
@ -281,7 +282,7 @@ func makeNodeInfo(sw *p2p.Switch, privKey acm.PrivKeyEd25519) *types.NodeInfo {
|
|||||||
func RunNode() {
|
func RunNode() {
|
||||||
// Create & start node
|
// Create & start node
|
||||||
n := NewNode()
|
n := NewNode()
|
||||||
l := p2p.NewDefaultListener("tcp", config.GetString("node_laddr"), false)
|
l := p2p.NewDefaultListener("tcp", config.GetString("node_laddr"))
|
||||||
n.AddListener(l)
|
n.AddListener(l)
|
||||||
err := n.Start()
|
err := n.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
func TestNodeStartStop(t *testing.T) {
|
func TestNodeStartStop(t *testing.T) {
|
||||||
// Create & start node
|
// Create & start node
|
||||||
n := NewNode()
|
n := NewNode()
|
||||||
l := p2p.NewDefaultListener("tcp", config.GetString("node_laddr"), false)
|
l := p2p.NewDefaultListener("tcp", config.GetString("node_laddr"))
|
||||||
n.AddListener(l)
|
n.AddListener(l)
|
||||||
n.Start()
|
n.Start()
|
||||||
log.Notice("Started node", "nodeInfo", n.sw.NodeInfo())
|
log.Notice("Started node", "nodeInfo", n.sw.NodeInfo())
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package consensus
|
package p2p
|
||||||
|
|
||||||
import (
|
import (
|
||||||
cfg "github.com/tendermint/tendermint/config"
|
cfg "github.com/tendermint/tendermint/config"
|
@ -46,7 +46,7 @@ func splitHostPort(addr string) (host string, port int) {
|
|||||||
return host, port
|
return host, port
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefaultListener(protocol string, lAddr string, requireUPNPHairpin bool) Listener {
|
func NewDefaultListener(protocol string, lAddr string) Listener {
|
||||||
// Local listen IP & port
|
// Local listen IP & port
|
||||||
lAddrIP, lAddrPort := splitHostPort(lAddr)
|
lAddrIP, lAddrPort := splitHostPort(lAddr)
|
||||||
|
|
||||||
@ -73,22 +73,12 @@ func NewDefaultListener(protocol string, lAddr string, requireUPNPHairpin bool)
|
|||||||
|
|
||||||
// Determine external address...
|
// Determine external address...
|
||||||
var extAddr *NetAddress
|
var extAddr *NetAddress
|
||||||
// If the lAddrIP is INADDR_ANY, try UPnP
|
if !config.GetBool("skip_upnp") {
|
||||||
if lAddrIP == "" || lAddrIP == "0.0.0.0" {
|
// If the lAddrIP is INADDR_ANY, try UPnP
|
||||||
if requireUPNPHairpin {
|
if lAddrIP == "" || lAddrIP == "0.0.0.0" {
|
||||||
upnpCapabilities, err := upnp.Probe()
|
extAddr = getUPNPExternalAddress(lAddrPort, listenerPort)
|
||||||
if err != nil {
|
|
||||||
log.Warn("Failed to probe UPNP", "error", err)
|
|
||||||
goto SKIP_UPNP
|
|
||||||
}
|
|
||||||
if !upnpCapabilities.Hairpin {
|
|
||||||
goto SKIP_UPNP
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
extAddr = getUPNPExternalAddress(lAddrPort, listenerPort)
|
|
||||||
}
|
}
|
||||||
SKIP_UPNP:
|
|
||||||
|
|
||||||
// Otherwise just use the local address...
|
// Otherwise just use the local address...
|
||||||
if extAddr == nil {
|
if extAddr == nil {
|
||||||
extAddr = getNaiveExternalAddress(listenerPort)
|
extAddr = getNaiveExternalAddress(listenerPort)
|
||||||
|
@ -7,9 +7,10 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
acm "github.com/tendermint/tendermint/account"
|
acm "github.com/tendermint/tendermint/account"
|
||||||
"github.com/tendermint/tendermint/wire"
|
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
|
_ "github.com/tendermint/tendermint/config/tendermint_test"
|
||||||
"github.com/tendermint/tendermint/types"
|
"github.com/tendermint/tendermint/types"
|
||||||
|
"github.com/tendermint/tendermint/wire"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PeerMessage struct {
|
type PeerMessage struct {
|
||||||
@ -97,7 +98,7 @@ func makeSwitchPair(t testing.TB, initSwitch func(*Switch) *Switch) (*Switch, *S
|
|||||||
s2.Start()
|
s2.Start()
|
||||||
|
|
||||||
// Create a listener for s1
|
// Create a listener for s1
|
||||||
l := NewDefaultListener("tcp", ":8001", true)
|
l := NewDefaultListener("tcp", ":8001")
|
||||||
|
|
||||||
// Dial the listener & add the connection to s2.
|
// Dial the listener & add the connection to s2.
|
||||||
lAddr := l.ExternalAddress()
|
lAddr := l.ExternalAddress()
|
||||||
|
@ -7,21 +7,21 @@ import (
|
|||||||
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GenPrivAccount() (*acm.PrivAccount, error) {
|
func GenPrivAccount() (*ctypes.ResultGenPrivAccount, error) {
|
||||||
return acm.GenPrivAccount(), nil
|
return &ctypes.ResultGenPrivAccount{acm.GenPrivAccount()}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the account is not known, returns nil, nil.
|
// If the account is not known, returns nil, nil.
|
||||||
func GetAccount(address []byte) (*acm.Account, error) {
|
func GetAccount(address []byte) (*ctypes.ResultGetAccount, error) {
|
||||||
cache := mempoolReactor.Mempool.GetCache()
|
cache := mempoolReactor.Mempool.GetCache()
|
||||||
account := cache.GetAccount(address)
|
account := cache.GetAccount(address)
|
||||||
if account == nil {
|
if account == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
return account, nil
|
return &ctypes.ResultGetAccount{account}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetStorage(address, key []byte) (*ctypes.ResponseGetStorage, error) {
|
func GetStorage(address, key []byte) (*ctypes.ResultGetStorage, error) {
|
||||||
state := consensusState.GetState()
|
state := consensusState.GetState()
|
||||||
account := state.GetAccount(address)
|
account := state.GetAccount(address)
|
||||||
if account == nil {
|
if account == nil {
|
||||||
@ -32,12 +32,12 @@ func GetStorage(address, key []byte) (*ctypes.ResponseGetStorage, error) {
|
|||||||
|
|
||||||
_, value := storageTree.Get(LeftPadWord256(key).Bytes())
|
_, value := storageTree.Get(LeftPadWord256(key).Bytes())
|
||||||
if value == nil {
|
if value == nil {
|
||||||
return &ctypes.ResponseGetStorage{key, nil}, nil
|
return &ctypes.ResultGetStorage{key, nil}, nil
|
||||||
}
|
}
|
||||||
return &ctypes.ResponseGetStorage{key, value.([]byte)}, nil
|
return &ctypes.ResultGetStorage{key, value.([]byte)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ListAccounts() (*ctypes.ResponseListAccounts, error) {
|
func ListAccounts() (*ctypes.ResultListAccounts, error) {
|
||||||
var blockHeight int
|
var blockHeight int
|
||||||
var accounts []*acm.Account
|
var accounts []*acm.Account
|
||||||
state := consensusState.GetState()
|
state := consensusState.GetState()
|
||||||
@ -46,10 +46,10 @@ func ListAccounts() (*ctypes.ResponseListAccounts, error) {
|
|||||||
accounts = append(accounts, value.(*acm.Account))
|
accounts = append(accounts, value.(*acm.Account))
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
return &ctypes.ResponseListAccounts{blockHeight, accounts}, nil
|
return &ctypes.ResultListAccounts{blockHeight, accounts}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func DumpStorage(address []byte) (*ctypes.ResponseDumpStorage, error) {
|
func DumpStorage(address []byte) (*ctypes.ResultDumpStorage, error) {
|
||||||
state := consensusState.GetState()
|
state := consensusState.GetState()
|
||||||
account := state.GetAccount(address)
|
account := state.GetAccount(address)
|
||||||
if account == nil {
|
if account == nil {
|
||||||
@ -63,5 +63,5 @@ func DumpStorage(address []byte) (*ctypes.ResponseDumpStorage, error) {
|
|||||||
key.([]byte), value.([]byte)})
|
key.([]byte), value.([]byte)})
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
return &ctypes.ResponseDumpStorage{storageRoot, storageItems}, nil
|
return &ctypes.ResultDumpStorage{storageRoot, storageItems}, nil
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import (
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
func BlockchainInfo(minHeight, maxHeight int) (*ctypes.ResponseBlockchainInfo, error) {
|
func BlockchainInfo(minHeight, maxHeight int) (*ctypes.ResultBlockchainInfo, error) {
|
||||||
if maxHeight == 0 {
|
if maxHeight == 0 {
|
||||||
maxHeight = blockStore.Height()
|
maxHeight = blockStore.Height()
|
||||||
} else {
|
} else {
|
||||||
@ -26,12 +26,12 @@ func BlockchainInfo(minHeight, maxHeight int) (*ctypes.ResponseBlockchainInfo, e
|
|||||||
blockMetas = append(blockMetas, blockMeta)
|
blockMetas = append(blockMetas, blockMeta)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ctypes.ResponseBlockchainInfo{blockStore.Height(), blockMetas}, nil
|
return &ctypes.ResultBlockchainInfo{blockStore.Height(), blockMetas}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
func GetBlock(height int) (*ctypes.ResponseGetBlock, error) {
|
func GetBlock(height int) (*ctypes.ResultGetBlock, error) {
|
||||||
if height == 0 {
|
if height == 0 {
|
||||||
return nil, fmt.Errorf("Height must be greater than 0")
|
return nil, fmt.Errorf("Height must be greater than 0")
|
||||||
}
|
}
|
||||||
@ -41,5 +41,5 @@ func GetBlock(height int) (*ctypes.ResponseGetBlock, error) {
|
|||||||
|
|
||||||
blockMeta := blockStore.LoadBlockMeta(height)
|
blockMeta := blockStore.LoadBlockMeta(height)
|
||||||
block := blockStore.LoadBlock(height)
|
block := blockStore.LoadBlock(height)
|
||||||
return &ctypes.ResponseGetBlock{blockMeta, block}, nil
|
return &ctypes.ResultGetBlock{blockMeta, block}, nil
|
||||||
}
|
}
|
||||||
|
@ -1,32 +1,32 @@
|
|||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/tendermint/tendermint/wire"
|
|
||||||
cm "github.com/tendermint/tendermint/consensus"
|
cm "github.com/tendermint/tendermint/consensus"
|
||||||
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||||
sm "github.com/tendermint/tendermint/state"
|
"github.com/tendermint/tendermint/types"
|
||||||
|
"github.com/tendermint/tendermint/wire"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ListValidators() (*ctypes.ResponseListValidators, error) {
|
func ListValidators() (*ctypes.ResultListValidators, error) {
|
||||||
var blockHeight int
|
var blockHeight int
|
||||||
var bondedValidators []*sm.Validator
|
var bondedValidators []*types.Validator
|
||||||
var unbondingValidators []*sm.Validator
|
var unbondingValidators []*types.Validator
|
||||||
|
|
||||||
state := consensusState.GetState()
|
state := consensusState.GetState()
|
||||||
blockHeight = state.LastBlockHeight
|
blockHeight = state.LastBlockHeight
|
||||||
state.BondedValidators.Iterate(func(index int, val *sm.Validator) bool {
|
state.BondedValidators.Iterate(func(index int, val *types.Validator) bool {
|
||||||
bondedValidators = append(bondedValidators, val)
|
bondedValidators = append(bondedValidators, val)
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
state.UnbondingValidators.Iterate(func(index int, val *sm.Validator) bool {
|
state.UnbondingValidators.Iterate(func(index int, val *types.Validator) bool {
|
||||||
unbondingValidators = append(unbondingValidators, val)
|
unbondingValidators = append(unbondingValidators, val)
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
return &ctypes.ResponseListValidators{blockHeight, bondedValidators, unbondingValidators}, nil
|
return &ctypes.ResultListValidators{blockHeight, bondedValidators, unbondingValidators}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func DumpConsensusState() (*ctypes.ResponseDumpConsensusState, error) {
|
func DumpConsensusState() (*ctypes.ResultDumpConsensusState, error) {
|
||||||
roundState := consensusState.GetRoundState()
|
roundState := consensusState.GetRoundState()
|
||||||
peerRoundStates := []string{}
|
peerRoundStates := []string{}
|
||||||
for _, peer := range p2pSwitch.Peers().List() {
|
for _, peer := range p2pSwitch.Peers().List() {
|
||||||
@ -36,5 +36,5 @@ func DumpConsensusState() (*ctypes.ResponseDumpConsensusState, error) {
|
|||||||
peerRoundStateStr := peer.Key + ":" + string(wire.JSONBytes(peerRoundState))
|
peerRoundStateStr := peer.Key + ":" + string(wire.JSONBytes(peerRoundState))
|
||||||
peerRoundStates = append(peerRoundStates, peerRoundStateStr)
|
peerRoundStates = append(peerRoundStates, peerRoundStateStr)
|
||||||
}
|
}
|
||||||
return &ctypes.ResponseDumpConsensusState{roundState.String(), peerRoundStates}, nil
|
return &ctypes.ResultDumpConsensusState{roundState.String(), peerRoundStates}, nil
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
// Note: tx must be signed
|
// Note: tx must be signed
|
||||||
func BroadcastTx(tx types.Tx) (*ctypes.Receipt, error) {
|
func BroadcastTx(tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
|
||||||
err := mempoolReactor.BroadcastTx(tx)
|
err := mempoolReactor.BroadcastTx(tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error broadcasting transaction: %v", err)
|
return nil, fmt.Errorf("Error broadcasting transaction: %v", err)
|
||||||
@ -26,9 +26,9 @@ func BroadcastTx(tx types.Tx) (*ctypes.Receipt, error) {
|
|||||||
contractAddr = state.NewContractAddress(callTx.Input.Address, callTx.Input.Sequence)
|
contractAddr = state.NewContractAddress(callTx.Input.Address, callTx.Input.Sequence)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &ctypes.Receipt{txHash, createsContract, contractAddr}, nil
|
return &ctypes.ResultBroadcastTx{ctypes.Receipt{txHash, createsContract, contractAddr}}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ListUnconfirmedTxs() ([]types.Tx, error) {
|
func ListUnconfirmedTxs() (*ctypes.ResultListUnconfirmedTxs, error) {
|
||||||
return mempoolReactor.Mempool.GetProposalTxs(), nil
|
return &ctypes.ResultListUnconfirmedTxs{mempoolReactor.Mempool.GetProposalTxs()}, nil
|
||||||
}
|
}
|
||||||
|
@ -7,16 +7,16 @@ import (
|
|||||||
"github.com/tendermint/tendermint/types"
|
"github.com/tendermint/tendermint/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetName(name string) (*types.NameRegEntry, error) {
|
func GetName(name string) (*ctypes.ResultGetName, error) {
|
||||||
st := consensusState.GetState() // performs a copy
|
st := consensusState.GetState() // performs a copy
|
||||||
entry := st.GetNameRegEntry(name)
|
entry := st.GetNameRegEntry(name)
|
||||||
if entry == nil {
|
if entry == nil {
|
||||||
return nil, fmt.Errorf("Name %s not found", name)
|
return nil, fmt.Errorf("Name %s not found", name)
|
||||||
}
|
}
|
||||||
return entry, nil
|
return &ctypes.ResultGetName{entry}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ListNames() (*ctypes.ResponseListNames, error) {
|
func ListNames() (*ctypes.ResultListNames, error) {
|
||||||
var blockHeight int
|
var blockHeight int
|
||||||
var names []*types.NameRegEntry
|
var names []*types.NameRegEntry
|
||||||
state := consensusState.GetState()
|
state := consensusState.GetState()
|
||||||
@ -25,5 +25,5 @@ func ListNames() (*ctypes.ResponseListNames, error) {
|
|||||||
names = append(names, value.(*types.NameRegEntry))
|
names = append(names, value.(*types.NameRegEntry))
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
return &ctypes.ResponseListNames{blockHeight, names}, nil
|
return &ctypes.ResultListNames{blockHeight, names}, nil
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
// cache the genesis state
|
// cache the genesis state
|
||||||
var genesisState *sm.State
|
var genesisState *sm.State
|
||||||
|
|
||||||
func Status() (*ctypes.ResponseStatus, error) {
|
func Status() (*ctypes.ResultStatus, error) {
|
||||||
db := dbm.NewMemDB()
|
db := dbm.NewMemDB()
|
||||||
if genesisState == nil {
|
if genesisState == nil {
|
||||||
genesisState = sm.MakeGenesisState(db, genDoc)
|
genesisState = sm.MakeGenesisState(db, genDoc)
|
||||||
@ -30,7 +30,7 @@ func Status() (*ctypes.ResponseStatus, error) {
|
|||||||
latestBlockTime = latestBlockMeta.Header.Time.UnixNano()
|
latestBlockTime = latestBlockMeta.Header.Time.UnixNano()
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ctypes.ResponseStatus{
|
return &ctypes.ResultStatus{
|
||||||
NodeInfo: p2pSwitch.NodeInfo(),
|
NodeInfo: p2pSwitch.NodeInfo(),
|
||||||
GenesisHash: genesisHash,
|
GenesisHash: genesisHash,
|
||||||
PubKey: privValidator.PubKey,
|
PubKey: privValidator.PubKey,
|
||||||
@ -41,7 +41,7 @@ func Status() (*ctypes.ResponseStatus, error) {
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
func NetInfo() (*ctypes.ResponseNetInfo, error) {
|
func NetInfo() (*ctypes.ResultNetInfo, error) {
|
||||||
listening := p2pSwitch.IsListening()
|
listening := p2pSwitch.IsListening()
|
||||||
listeners := []string{}
|
listeners := []string{}
|
||||||
for _, listener := range p2pSwitch.Listeners() {
|
for _, listener := range p2pSwitch.Listeners() {
|
||||||
@ -54,7 +54,7 @@ func NetInfo() (*ctypes.ResponseNetInfo, error) {
|
|||||||
IsOutbound: peer.IsOutbound(),
|
IsOutbound: peer.IsOutbound(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return &ctypes.ResponseNetInfo{
|
return &ctypes.ResultNetInfo{
|
||||||
Listening: listening,
|
Listening: listening,
|
||||||
Listeners: listeners,
|
Listeners: listeners,
|
||||||
Peers: peers,
|
Peers: peers,
|
||||||
@ -63,6 +63,6 @@ func NetInfo() (*ctypes.ResponseNetInfo, error) {
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
func Genesis() (*sm.GenesisDoc, error) {
|
func Genesis() (*ctypes.ResultGenesis, error) {
|
||||||
return genDoc, nil
|
return &ctypes.ResultGenesis{genDoc}, nil
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,8 @@ import (
|
|||||||
"github.com/tendermint/tendermint/consensus"
|
"github.com/tendermint/tendermint/consensus"
|
||||||
mempl "github.com/tendermint/tendermint/mempool"
|
mempl "github.com/tendermint/tendermint/mempool"
|
||||||
"github.com/tendermint/tendermint/p2p"
|
"github.com/tendermint/tendermint/p2p"
|
||||||
"github.com/tendermint/tendermint/state"
|
stypes "github.com/tendermint/tendermint/state/types"
|
||||||
|
"github.com/tendermint/tendermint/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
var blockStore *bc.BlockStore
|
var blockStore *bc.BlockStore
|
||||||
@ -13,8 +14,8 @@ var consensusState *consensus.ConsensusState
|
|||||||
var consensusReactor *consensus.ConsensusReactor
|
var consensusReactor *consensus.ConsensusReactor
|
||||||
var mempoolReactor *mempl.MempoolReactor
|
var mempoolReactor *mempl.MempoolReactor
|
||||||
var p2pSwitch *p2p.Switch
|
var p2pSwitch *p2p.Switch
|
||||||
var privValidator *state.PrivValidator
|
var privValidator *types.PrivValidator
|
||||||
var genDoc *state.GenesisDoc // cache the genesis structure
|
var genDoc *stypes.GenesisDoc // cache the genesis structure
|
||||||
|
|
||||||
func SetBlockStore(bs *bc.BlockStore) {
|
func SetBlockStore(bs *bc.BlockStore) {
|
||||||
blockStore = bs
|
blockStore = bs
|
||||||
@ -36,10 +37,10 @@ func SetSwitch(sw *p2p.Switch) {
|
|||||||
p2pSwitch = sw
|
p2pSwitch = sw
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetPrivValidator(pv *state.PrivValidator) {
|
func SetPrivValidator(pv *types.PrivValidator) {
|
||||||
privValidator = pv
|
privValidator = pv
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetGenDoc(doc *state.GenesisDoc) {
|
func SetGenDoc(doc *stypes.GenesisDoc) {
|
||||||
genDoc = doc
|
genDoc = doc
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ func toVMAccount(acc *acm.Account) *vm.Account {
|
|||||||
|
|
||||||
// Run a contract's code on an isolated and unpersisted state
|
// Run a contract's code on an isolated and unpersisted state
|
||||||
// Cannot be used to create new contracts
|
// Cannot be used to create new contracts
|
||||||
func Call(fromAddress, toAddress, data []byte) (*ctypes.ResponseCall, error) {
|
func Call(fromAddress, toAddress, data []byte) (*ctypes.ResultCall, error) {
|
||||||
st := consensusState.GetState() // performs a copy
|
st := consensusState.GetState() // performs a copy
|
||||||
cache := state.NewBlockCache(st)
|
cache := state.NewBlockCache(st)
|
||||||
outAcc := cache.GetAccount(toAddress)
|
outAcc := cache.GetAccount(toAddress)
|
||||||
@ -47,12 +47,12 @@ func Call(fromAddress, toAddress, data []byte) (*ctypes.ResponseCall, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &ctypes.ResponseCall{Return: ret}, nil
|
return &ctypes.ResultCall{Return: ret}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the given code on an isolated and unpersisted state
|
// Run the given code on an isolated and unpersisted state
|
||||||
// Cannot be used to create new contracts
|
// Cannot be used to create new contracts
|
||||||
func CallCode(fromAddress, code, data []byte) (*ctypes.ResponseCall, error) {
|
func CallCode(fromAddress, code, data []byte) (*ctypes.ResultCall, error) {
|
||||||
|
|
||||||
st := consensusState.GetState() // performs a copy
|
st := consensusState.GetState() // performs a copy
|
||||||
cache := mempoolReactor.Mempool.GetCache()
|
cache := mempoolReactor.Mempool.GetCache()
|
||||||
@ -72,12 +72,12 @@ func CallCode(fromAddress, code, data []byte) (*ctypes.ResponseCall, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &ctypes.ResponseCall{Return: ret}, nil
|
return &ctypes.ResultCall{Return: ret}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
func SignTx(tx types.Tx, privAccounts []*acm.PrivAccount) (types.Tx, error) {
|
func SignTx(tx types.Tx, privAccounts []*acm.PrivAccount) (*ctypes.ResultSignTx, error) {
|
||||||
// more checks?
|
// more checks?
|
||||||
|
|
||||||
for i, privAccount := range privAccounts {
|
for i, privAccount := range privAccounts {
|
||||||
@ -112,5 +112,5 @@ func SignTx(tx types.Tx, privAccounts []*acm.PrivAccount) (types.Tx, error) {
|
|||||||
rebondTx := tx.(*types.RebondTx)
|
rebondTx := tx.(*types.RebondTx)
|
||||||
rebondTx.Signature = privAccounts[0].Sign(config.GetString("chain_id"), rebondTx).(acm.SignatureEd25519)
|
rebondTx.Signature = privAccounts[0].Sign(config.GetString("chain_id"), rebondTx).(acm.SignatureEd25519)
|
||||||
}
|
}
|
||||||
return tx, nil
|
return &ctypes.ResultSignTx{tx}, nil
|
||||||
}
|
}
|
||||||
|
@ -2,53 +2,48 @@ package core_types
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
acm "github.com/tendermint/tendermint/account"
|
acm "github.com/tendermint/tendermint/account"
|
||||||
sm "github.com/tendermint/tendermint/state"
|
stypes "github.com/tendermint/tendermint/state/types"
|
||||||
"github.com/tendermint/tendermint/types"
|
"github.com/tendermint/tendermint/types"
|
||||||
|
"github.com/tendermint/tendermint/wire"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ResponseGetStorage struct {
|
type ResultGetStorage struct {
|
||||||
Key []byte `json:"key"`
|
Key []byte `json:"key"`
|
||||||
Value []byte `json:"value"`
|
Value []byte `json:"value"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResponseCall struct {
|
type ResultCall struct {
|
||||||
Return []byte `json:"return"`
|
Return []byte `json:"return"`
|
||||||
GasUsed int64 `json:"gas_used"`
|
GasUsed int64 `json:"gas_used"`
|
||||||
// TODO ...
|
// TODO ...
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResponseListAccounts struct {
|
type ResultListAccounts struct {
|
||||||
BlockHeight int `json:"block_height"`
|
BlockHeight int `json:"block_height"`
|
||||||
Accounts []*acm.Account `json:"accounts"`
|
Accounts []*acm.Account `json:"accounts"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ResultDumpStorage struct {
|
||||||
|
StorageRoot []byte `json:"storage_root"`
|
||||||
|
StorageItems []StorageItem `json:"storage_items"`
|
||||||
|
}
|
||||||
|
|
||||||
type StorageItem struct {
|
type StorageItem struct {
|
||||||
Key []byte `json:"key"`
|
Key []byte `json:"key"`
|
||||||
Value []byte `json:"value"`
|
Value []byte `json:"value"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResponseDumpStorage struct {
|
type ResultBlockchainInfo struct {
|
||||||
StorageRoot []byte `json:"storage_root"`
|
|
||||||
StorageItems []StorageItem `json:"storage_items"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ResponseBlockchainInfo struct {
|
|
||||||
LastHeight int `json:"last_height"`
|
LastHeight int `json:"last_height"`
|
||||||
BlockMetas []*types.BlockMeta `json:"block_metas"`
|
BlockMetas []*types.BlockMeta `json:"block_metas"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResponseGetBlock struct {
|
type ResultGetBlock struct {
|
||||||
BlockMeta *types.BlockMeta `json:"block_meta"`
|
BlockMeta *types.BlockMeta `json:"block_meta"`
|
||||||
Block *types.Block `json:"block"`
|
Block *types.Block `json:"block"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Receipt struct {
|
type ResultStatus struct {
|
||||||
TxHash []byte `json:"tx_hash"`
|
|
||||||
CreatesContract uint8 `json:"creates_contract"`
|
|
||||||
ContractAddr []byte `json:"contract_addr"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ResponseStatus struct {
|
|
||||||
NodeInfo *types.NodeInfo `json:"node_info"`
|
NodeInfo *types.NodeInfo `json:"node_info"`
|
||||||
GenesisHash []byte `json:"genesis_hash"`
|
GenesisHash []byte `json:"genesis_hash"`
|
||||||
PubKey acm.PubKey `json:"pub_key"`
|
PubKey acm.PubKey `json:"pub_key"`
|
||||||
@ -57,7 +52,7 @@ type ResponseStatus struct {
|
|||||||
LatestBlockTime int64 `json:"latest_block_time"` // nano
|
LatestBlockTime int64 `json:"latest_block_time"` // nano
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResponseNetInfo struct {
|
type ResultNetInfo struct {
|
||||||
Listening bool `json:"listening"`
|
Listening bool `json:"listening"`
|
||||||
Listeners []string `json:"listeners"`
|
Listeners []string `json:"listeners"`
|
||||||
Peers []Peer `json:"peers"`
|
Peers []Peer `json:"peers"`
|
||||||
@ -68,26 +63,115 @@ type Peer struct {
|
|||||||
IsOutbound bool `json:"is_outbound"`
|
IsOutbound bool `json:"is_outbound"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResponseListValidators struct {
|
type ResultListValidators struct {
|
||||||
BlockHeight int `json:"block_height"`
|
BlockHeight int `json:"block_height"`
|
||||||
BondedValidators []*sm.Validator `json:"bonded_validators"`
|
BondedValidators []*types.Validator `json:"bonded_validators"`
|
||||||
UnbondingValidators []*sm.Validator `json:"unbonding_validators"`
|
UnbondingValidators []*types.Validator `json:"unbonding_validators"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResponseDumpConsensusState struct {
|
type ResultDumpConsensusState struct {
|
||||||
RoundState string `json:"round_state"`
|
RoundState string `json:"round_state"`
|
||||||
PeerRoundStates []string `json:"peer_round_states"`
|
PeerRoundStates []string `json:"peer_round_states"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResponseListNames struct {
|
type ResultListNames struct {
|
||||||
BlockHeight int `json:"block_height"`
|
BlockHeight int `json:"block_height"`
|
||||||
Names []*types.NameRegEntry `json:"names"`
|
Names []*types.NameRegEntry `json:"names"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------
|
type ResultGenPrivAccount struct {
|
||||||
// event responses
|
PrivAccount *acm.PrivAccount `json:"priv_account"`
|
||||||
|
|
||||||
type ResponseEvent struct {
|
|
||||||
Event string `json:"event"`
|
|
||||||
Data interface{} `json:"data"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ResultGetAccount struct {
|
||||||
|
Account *acm.Account `json:"account"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResultBroadcastTx struct {
|
||||||
|
Receipt Receipt `json:"receipt"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Receipt struct {
|
||||||
|
TxHash []byte `json:"tx_hash"`
|
||||||
|
CreatesContract uint8 `json:"creates_contract"`
|
||||||
|
ContractAddr []byte `json:"contract_addr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResultListUnconfirmedTxs struct {
|
||||||
|
Txs []types.Tx `json:"txs"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResultGetName struct {
|
||||||
|
Entry *types.NameRegEntry `json:"entry"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResultGenesis struct {
|
||||||
|
Genesis *stypes.GenesisDoc `json:"genesis"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResultSignTx struct {
|
||||||
|
Tx types.Tx `json:"tx"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ResultEvent struct {
|
||||||
|
Event string `json:"event"`
|
||||||
|
Data types.EventData `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------
|
||||||
|
// response & result types
|
||||||
|
|
||||||
|
type Response struct {
|
||||||
|
JSONRPC string `json:"jsonrpc"`
|
||||||
|
Id string `json:"id"`
|
||||||
|
Result Result `json:"result"`
|
||||||
|
Error string `json:"error"`
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
ResultTypeGetStorage = byte(0x01)
|
||||||
|
ResultTypeCall = byte(0x02)
|
||||||
|
ResultTypeListAccounts = byte(0x03)
|
||||||
|
ResultTypeDumpStorage = byte(0x04)
|
||||||
|
ResultTypeBlockchainInfo = byte(0x05)
|
||||||
|
ResultTypeGetBlock = byte(0x06)
|
||||||
|
ResultTypeStatus = byte(0x07)
|
||||||
|
ResultTypeNetInfo = byte(0x08)
|
||||||
|
ResultTypeListValidators = byte(0x09)
|
||||||
|
ResultTypeDumpConsensusState = byte(0x0A)
|
||||||
|
ResultTypeListNames = byte(0x0B)
|
||||||
|
ResultTypeGenPrivAccount = byte(0x0C) //*acm.PrivAccount
|
||||||
|
ResultTypeGetAccount = byte(0x0D) //*acm.Account
|
||||||
|
ResultTypeBroadcastTx = byte(0x0E) //*types.Receipt
|
||||||
|
ResultTypeListUnconfirmedTxs = byte(0x0F) //[]types.Tx
|
||||||
|
ResultTypeGetName = byte(0x10) // *types.NameRegEntry
|
||||||
|
ResultTypeGenesis = byte(0x11) // *stypes.GenesisDoc
|
||||||
|
ResultTypeSignTx = byte(0x12) // Tx >>>> double interface!
|
||||||
|
ResultTypeEvent = byte(0x13) // so websockets can respond to rpc functions
|
||||||
|
)
|
||||||
|
|
||||||
|
type Result interface{}
|
||||||
|
|
||||||
|
// for wire.readReflect
|
||||||
|
var _ = wire.RegisterInterface(
|
||||||
|
struct{ Result }{},
|
||||||
|
wire.ConcreteType{&ResultGetStorage{}, ResultTypeGetStorage},
|
||||||
|
wire.ConcreteType{&ResultCall{}, ResultTypeCall},
|
||||||
|
wire.ConcreteType{&ResultListAccounts{}, ResultTypeListAccounts},
|
||||||
|
wire.ConcreteType{&ResultDumpStorage{}, ResultTypeDumpStorage},
|
||||||
|
wire.ConcreteType{&ResultBlockchainInfo{}, ResultTypeBlockchainInfo},
|
||||||
|
wire.ConcreteType{&ResultGetBlock{}, ResultTypeGetBlock},
|
||||||
|
wire.ConcreteType{&ResultStatus{}, ResultTypeStatus},
|
||||||
|
wire.ConcreteType{&ResultNetInfo{}, ResultTypeNetInfo},
|
||||||
|
wire.ConcreteType{&ResultListValidators{}, ResultTypeListValidators},
|
||||||
|
wire.ConcreteType{&ResultDumpConsensusState{}, ResultTypeDumpConsensusState},
|
||||||
|
wire.ConcreteType{&ResultListNames{}, ResultTypeListNames},
|
||||||
|
wire.ConcreteType{&ResultGenPrivAccount{}, ResultTypeGenPrivAccount},
|
||||||
|
wire.ConcreteType{&ResultGetAccount{}, ResultTypeGetAccount},
|
||||||
|
wire.ConcreteType{&ResultBroadcastTx{}, ResultTypeBroadcastTx},
|
||||||
|
wire.ConcreteType{&ResultListUnconfirmedTxs{}, ResultTypeListUnconfirmedTxs},
|
||||||
|
wire.ConcreteType{&ResultGetName{}, ResultTypeGetName},
|
||||||
|
wire.ConcreteType{&ResultGenesis{}, ResultTypeGenesis},
|
||||||
|
wire.ConcreteType{&ResultSignTx{}, ResultTypeSignTx},
|
||||||
|
wire.ConcreteType{&ResultEvent{}, ResultTypeEvent},
|
||||||
|
)
|
||||||
|
File diff suppressed because it is too large
Load Diff
7
rpc/core_client/log.go
Normal file
7
rpc/core_client/log.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package core_client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/tendermint/tendermint/Godeps/_workspace/src/github.com/tendermint/log15"
|
||||||
|
)
|
||||||
|
|
||||||
|
var log = log15.New("module", "core_client")
|
@ -1,4 +1,4 @@
|
|||||||
package rpcclient
|
package core_client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@ -8,27 +8,28 @@ import (
|
|||||||
"github.com/tendermint/tendermint/Godeps/_workspace/src/github.com/gorilla/websocket"
|
"github.com/tendermint/tendermint/Godeps/_workspace/src/github.com/gorilla/websocket"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
_ "github.com/tendermint/tendermint/config/tendermint_test"
|
_ "github.com/tendermint/tendermint/config/tendermint_test"
|
||||||
|
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||||
"github.com/tendermint/tendermint/rpc/types"
|
"github.com/tendermint/tendermint/rpc/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
const wsEventsChannelCapacity = 10
|
const wsEventsChannelCapacity = 10
|
||||||
const wsResponsesChannelCapacity = 10
|
const wsResultsChannelCapacity = 10
|
||||||
|
|
||||||
type WSClient struct {
|
type WSClient struct {
|
||||||
QuitService
|
QuitService
|
||||||
Address string
|
Address string
|
||||||
*websocket.Conn
|
*websocket.Conn
|
||||||
EventsCh chan rpctypes.RPCEventResult
|
EventsCh chan ctypes.ResultEvent
|
||||||
ResponsesCh chan rpctypes.RPCResponse
|
ResultsCh chan ctypes.Result
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a new connection
|
// create a new connection
|
||||||
func NewWSClient(addr string) *WSClient {
|
func NewWSClient(addr string) *WSClient {
|
||||||
wsClient := &WSClient{
|
wsClient := &WSClient{
|
||||||
Address: addr,
|
Address: addr,
|
||||||
Conn: nil,
|
Conn: nil,
|
||||||
EventsCh: make(chan rpctypes.RPCEventResult, wsEventsChannelCapacity),
|
EventsCh: make(chan ctypes.ResultEvent, wsEventsChannelCapacity),
|
||||||
ResponsesCh: make(chan rpctypes.RPCResponse, wsResponsesChannelCapacity),
|
ResultsCh: make(chan ctypes.Result, wsResultsChannelCapacity),
|
||||||
}
|
}
|
||||||
wsClient.QuitService = *NewQuitService(log, "WSClient", wsClient)
|
wsClient.QuitService = *NewQuitService(log, "WSClient", wsClient)
|
||||||
return wsClient
|
return wsClient
|
||||||
@ -68,19 +69,16 @@ func (wsc *WSClient) receiveEventsRoutine() {
|
|||||||
wsc.Stop()
|
wsc.Stop()
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
var response rpctypes.RPCResponse
|
var response ctypes.Response
|
||||||
if err := json.Unmarshal(data, &response); err != nil {
|
if err := json.Unmarshal(data, &response); err != nil {
|
||||||
log.Info(Fmt("WSClient failed to parse message: %v", err))
|
log.Info(Fmt("WSClient failed to parse message: %v", err))
|
||||||
wsc.Stop()
|
wsc.Stop()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if strings.HasSuffix(response.Id, "#event") {
|
if strings.HasSuffix(response.Id, "#event") {
|
||||||
result := response.Result.(map[string]interface{})
|
wsc.EventsCh <- response.Result.(ctypes.ResultEvent)
|
||||||
event := result["event"].(string)
|
|
||||||
data := result["data"]
|
|
||||||
wsc.EventsCh <- rpctypes.RPCEventResult{event, data}
|
|
||||||
} else {
|
} else {
|
||||||
wsc.ResponsesCh <- response
|
wsc.ResultsCh <- response.Result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/tendermint/tendermint/Godeps/_workspace/src/github.com/gorilla/websocket"
|
"github.com/tendermint/tendermint/Godeps/_workspace/src/github.com/gorilla/websocket"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
"github.com/tendermint/tendermint/events"
|
"github.com/tendermint/tendermint/events"
|
||||||
|
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||||
. "github.com/tendermint/tendermint/rpc/types"
|
. "github.com/tendermint/tendermint/rpc/types"
|
||||||
"github.com/tendermint/tendermint/wire"
|
"github.com/tendermint/tendermint/wire"
|
||||||
)
|
)
|
||||||
@ -338,7 +339,7 @@ func (wsc *WSConnection) readRoutine() {
|
|||||||
log.Notice("Subscribe to event", "id", wsc.id, "event", event)
|
log.Notice("Subscribe to event", "id", wsc.id, "event", event)
|
||||||
wsc.evsw.AddListenerForEvent(wsc.id, event, func(msg interface{}) {
|
wsc.evsw.AddListenerForEvent(wsc.id, event, func(msg interface{}) {
|
||||||
// NOTE: RPCResponses of subscribed events have id suffix "#event"
|
// NOTE: RPCResponses of subscribed events have id suffix "#event"
|
||||||
wsc.writeRPCResponse(NewRPCResponse(request.Id+"#event", RPCEventResult{event, msg}, ""))
|
wsc.writeRPCResponse(NewRPCResponse(request.Id+"#event", ctypes.ResultEvent{event, msg}, ""))
|
||||||
})
|
})
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -11,9 +11,9 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/tendermint/tendermint/alert"
|
"github.com/tendermint/tendermint/alert"
|
||||||
"github.com/tendermint/tendermint/wire"
|
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
. "github.com/tendermint/tendermint/rpc/types"
|
. "github.com/tendermint/tendermint/rpc/types"
|
||||||
|
"github.com/tendermint/tendermint/wire"
|
||||||
)
|
)
|
||||||
|
|
||||||
func StartHTTPServer(listenAddr string, handler http.Handler) (net.Listener, error) {
|
func StartHTTPServer(listenAddr string, handler http.Handler) (net.Listener, error) {
|
||||||
@ -33,10 +33,10 @@ func StartHTTPServer(listenAddr string, handler http.Handler) (net.Listener, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
func WriteRPCResponse(w http.ResponseWriter, res RPCResponse) {
|
func WriteRPCResponse(w http.ResponseWriter, res RPCResponse) {
|
||||||
buf, n, err := new(bytes.Buffer), new(int64), new(error)
|
buf, n, err := new(bytes.Buffer), int64(0), error(nil)
|
||||||
wire.WriteJSON(res, buf, n, err)
|
wire.WriteJSON(res, buf, &n, &err)
|
||||||
if *err != nil {
|
if err != nil {
|
||||||
log.Warn("Failed to write RPC response", "error", err)
|
log.Error("Failed to write RPC response", "error", err, "res", res)
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
@ -120,7 +120,7 @@ func TestWSCallWait(t *testing.T) {
|
|||||||
tx := makeDefaultCallTx(t, wsTyp, nil, code, amt, gasLim, fee)
|
tx := makeDefaultCallTx(t, wsTyp, nil, code, amt, gasLim, fee)
|
||||||
receipt := broadcastTx(t, wsTyp, tx)
|
receipt := broadcastTx(t, wsTyp, tx)
|
||||||
contractAddr = receipt.ContractAddr
|
contractAddr = receipt.ContractAddr
|
||||||
}, unmarshalValidateCall(amt, returnCode))
|
}, unmarshalValidateTx(amt, returnCode))
|
||||||
|
|
||||||
// susbscribe to the new contract
|
// susbscribe to the new contract
|
||||||
amt = int64(10001)
|
amt = int64(10001)
|
||||||
@ -135,7 +135,7 @@ func TestWSCallWait(t *testing.T) {
|
|||||||
tx := makeDefaultCallTx(t, wsTyp, contractAddr, data, amt, gasLim, fee)
|
tx := makeDefaultCallTx(t, wsTyp, contractAddr, data, amt, gasLim, fee)
|
||||||
receipt := broadcastTx(t, wsTyp, tx)
|
receipt := broadcastTx(t, wsTyp, tx)
|
||||||
contractAddr = receipt.ContractAddr
|
contractAddr = receipt.ContractAddr
|
||||||
}, unmarshalValidateCall(amt, returnVal))
|
}, unmarshalValidateTx(amt, returnVal))
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a contract and send it a msg without waiting. wait for contract event
|
// create a contract and send it a msg without waiting. wait for contract event
|
||||||
@ -165,7 +165,7 @@ func TestWSCallNoWait(t *testing.T) {
|
|||||||
waitForEvent(t, con, eid, true, func() {
|
waitForEvent(t, con, eid, true, func() {
|
||||||
tx := makeDefaultCallTx(t, wsTyp, contractAddr, data, amt, gasLim, fee)
|
tx := makeDefaultCallTx(t, wsTyp, contractAddr, data, amt, gasLim, fee)
|
||||||
broadcastTx(t, wsTyp, tx)
|
broadcastTx(t, wsTyp, tx)
|
||||||
}, unmarshalValidateCall(amt, returnVal))
|
}, unmarshalValidateTx(amt, returnVal))
|
||||||
}
|
}
|
||||||
|
|
||||||
// create two contracts, one of which calls the other
|
// create two contracts, one of which calls the other
|
||||||
@ -208,5 +208,5 @@ func TestWSCallCall(t *testing.T) {
|
|||||||
tx := makeDefaultCallTx(t, wsTyp, contractAddr2, nil, amt, gasLim, fee)
|
tx := makeDefaultCallTx(t, wsTyp, contractAddr2, nil, amt, gasLim, fee)
|
||||||
broadcastTx(t, wsTyp, tx)
|
broadcastTx(t, wsTyp, tx)
|
||||||
*txid = types.TxID(chainID, tx)
|
*txid = types.TxID(chainID, tx)
|
||||||
}, unmarshalValidateCallCall(user[0].Address, returnVal, txid))
|
}, unmarshalValidateCall(user[0].Address, returnVal, txid))
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@ import (
|
|||||||
"github.com/tendermint/tendermint/p2p"
|
"github.com/tendermint/tendermint/p2p"
|
||||||
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||||
cclient "github.com/tendermint/tendermint/rpc/core_client"
|
cclient "github.com/tendermint/tendermint/rpc/core_client"
|
||||||
"github.com/tendermint/tendermint/state"
|
|
||||||
"github.com/tendermint/tendermint/types"
|
"github.com/tendermint/tendermint/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -51,7 +50,7 @@ func makeUsers(n int) []*acm.PrivAccount {
|
|||||||
func newNode(ready chan struct{}) {
|
func newNode(ready chan struct{}) {
|
||||||
// Create & start node
|
// Create & start node
|
||||||
node = nm.NewNode()
|
node = nm.NewNode()
|
||||||
l := p2p.NewDefaultListener("tcp", config.GetString("node_laddr"), false)
|
l := p2p.NewDefaultListener("tcp", config.GetString("node_laddr"))
|
||||||
node.AddListener(l)
|
node.AddListener(l)
|
||||||
node.Start()
|
node.Start()
|
||||||
|
|
||||||
@ -69,7 +68,7 @@ func init() {
|
|||||||
chainID = config.GetString("chain_id")
|
chainID = config.GetString("chain_id")
|
||||||
|
|
||||||
// Save new priv_validator file.
|
// Save new priv_validator file.
|
||||||
priv := &state.PrivValidator{
|
priv := &types.PrivValidator{
|
||||||
Address: user[0].Address,
|
Address: user[0].Address,
|
||||||
PubKey: acm.PubKeyEd25519(user[0].PubKey.(acm.PubKeyEd25519)),
|
PubKey: acm.PubKeyEd25519(user[0].PubKey.(acm.PubKeyEd25519)),
|
||||||
PrivKey: acm.PrivKeyEd25519(user[0].PrivKey.(acm.PrivKeyEd25519)),
|
PrivKey: acm.PrivKeyEd25519(user[0].PrivKey.(acm.PrivKeyEd25519)),
|
||||||
@ -126,10 +125,10 @@ func getNonce(t *testing.T, typ string, addr []byte) int {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if ac == nil {
|
if ac.Account == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return ac.Sequence
|
return ac.Account.Sequence
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the account
|
// get the account
|
||||||
@ -139,7 +138,7 @@ func getAccount(t *testing.T, typ string, addr []byte) *acm.Account {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
return ac
|
return ac.Account
|
||||||
}
|
}
|
||||||
|
|
||||||
// sign transaction
|
// sign transaction
|
||||||
@ -149,22 +148,22 @@ func signTx(t *testing.T, typ string, tx types.Tx, privAcc *acm.PrivAccount) typ
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
return signedTx
|
return signedTx.Tx
|
||||||
}
|
}
|
||||||
|
|
||||||
// broadcast transaction
|
// broadcast transaction
|
||||||
func broadcastTx(t *testing.T, typ string, tx types.Tx) *ctypes.Receipt {
|
func broadcastTx(t *testing.T, typ string, tx types.Tx) ctypes.Receipt {
|
||||||
client := clients[typ]
|
client := clients[typ]
|
||||||
rec, err := client.BroadcastTx(tx)
|
rec, err := client.BroadcastTx(tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
mempoolCount += 1
|
mempoolCount += 1
|
||||||
return rec
|
return rec.Receipt
|
||||||
}
|
}
|
||||||
|
|
||||||
// dump all storage for an account. currently unused
|
// dump all storage for an account. currently unused
|
||||||
func dumpStorage(t *testing.T, addr []byte) ctypes.ResponseDumpStorage {
|
func dumpStorage(t *testing.T, addr []byte) ctypes.ResultDumpStorage {
|
||||||
client := clients["HTTP"]
|
client := clients["HTTP"]
|
||||||
resp, err := client.DumpStorage(addr)
|
resp, err := client.DumpStorage(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -213,7 +212,7 @@ func getNameRegEntry(t *testing.T, typ string, name string) *types.NameRegEntry
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
return entry
|
return entry.Entry
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
|
@ -28,7 +28,7 @@ func testGenPriv(t *testing.T, typ string) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if len(privAcc.Address) == 0 {
|
if len(privAcc.PrivAccount.Address) == 0 {
|
||||||
t.Fatal("Failed to generate an address")
|
t.Fatal("Failed to generate an address")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package rpctest
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
@ -10,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"github.com/tendermint/tendermint/Godeps/_workspace/src/github.com/gorilla/websocket"
|
"github.com/tendermint/tendermint/Godeps/_workspace/src/github.com/gorilla/websocket"
|
||||||
_ "github.com/tendermint/tendermint/config/tendermint_test"
|
_ "github.com/tendermint/tendermint/config/tendermint_test"
|
||||||
|
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||||
"github.com/tendermint/tendermint/rpc/types"
|
"github.com/tendermint/tendermint/rpc/types"
|
||||||
"github.com/tendermint/tendermint/types"
|
"github.com/tendermint/tendermint/types"
|
||||||
"github.com/tendermint/tendermint/wire"
|
"github.com/tendermint/tendermint/wire"
|
||||||
@ -75,14 +75,14 @@ func waitForEvent(t *testing.T, con *websocket.Conn, eventid string, dieOnTimeou
|
|||||||
} else {
|
} else {
|
||||||
// if the event id isnt what we're waiting on
|
// if the event id isnt what we're waiting on
|
||||||
// ignore it
|
// ignore it
|
||||||
var response struct {
|
var response ctypes.Response
|
||||||
Result rpctypes.RPCEventResult `json:"result"`
|
var err error
|
||||||
}
|
wire.ReadJSON(&response, p, &err)
|
||||||
if err := json.Unmarshal(p, &response); err != nil {
|
if err != nil {
|
||||||
errCh <- err
|
errCh <- err
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if response.Result.Event == eventid {
|
if response.Result.(*ctypes.ResultEvent).Event == eventid {
|
||||||
goodCh <- p
|
goodCh <- p
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -109,6 +109,7 @@ func waitForEvent(t *testing.T, con *websocket.Conn, eventid string, dieOnTimeou
|
|||||||
// run the check
|
// run the check
|
||||||
err := check(eventid, p)
|
err := check(eventid, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -124,15 +125,7 @@ func waitForEvent(t *testing.T, con *websocket.Conn, eventid string, dieOnTimeou
|
|||||||
|
|
||||||
func unmarshalResponseNewBlock(b []byte) (*types.Block, error) {
|
func unmarshalResponseNewBlock(b []byte) (*types.Block, error) {
|
||||||
// unmarshall and assert somethings
|
// unmarshall and assert somethings
|
||||||
var response struct {
|
var response ctypes.Response
|
||||||
JSONRPC string `json:"jsonrpc"`
|
|
||||||
Id string `json:"id"`
|
|
||||||
Result struct {
|
|
||||||
Event string `json:"event"`
|
|
||||||
Data *types.Block `json:"data"`
|
|
||||||
} `json:"result"`
|
|
||||||
Error string `json:"error"`
|
|
||||||
}
|
|
||||||
var err error
|
var err error
|
||||||
wire.ReadJSON(&response, b, &err)
|
wire.ReadJSON(&response, b, &err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -141,7 +134,7 @@ func unmarshalResponseNewBlock(b []byte) (*types.Block, error) {
|
|||||||
if response.Error != "" {
|
if response.Error != "" {
|
||||||
return nil, fmt.Errorf(response.Error)
|
return nil, fmt.Errorf(response.Error)
|
||||||
}
|
}
|
||||||
block := response.Result.Data
|
block := response.Result.(*ctypes.ResultEvent).Data.(types.EventDataNewBlock).Block
|
||||||
return block, nil
|
return block, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,15 +185,7 @@ func unmarshalValidateBlockchain(t *testing.T, con *websocket.Conn, eid string)
|
|||||||
func unmarshalValidateSend(amt int64, toAddr []byte) func(string, []byte) error {
|
func unmarshalValidateSend(amt int64, toAddr []byte) func(string, []byte) error {
|
||||||
return func(eid string, b []byte) error {
|
return func(eid string, b []byte) error {
|
||||||
// unmarshal and assert correctness
|
// unmarshal and assert correctness
|
||||||
var response struct {
|
var response ctypes.Response
|
||||||
JSONRPC string `json:"jsonrpc"`
|
|
||||||
Id string `json:"id"`
|
|
||||||
Result struct {
|
|
||||||
Event string `json:"event"`
|
|
||||||
Data types.EventMsgTx `json:"data"`
|
|
||||||
} `json:"result"`
|
|
||||||
Error string `json:"error"`
|
|
||||||
}
|
|
||||||
var err error
|
var err error
|
||||||
wire.ReadJSON(&response, b, &err)
|
wire.ReadJSON(&response, b, &err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -209,39 +194,27 @@ func unmarshalValidateSend(amt int64, toAddr []byte) func(string, []byte) error
|
|||||||
if response.Error != "" {
|
if response.Error != "" {
|
||||||
return fmt.Errorf(response.Error)
|
return fmt.Errorf(response.Error)
|
||||||
}
|
}
|
||||||
if eid != response.Result.Event {
|
if eid != response.Result.(*ctypes.ResultEvent).Event {
|
||||||
return fmt.Errorf("Eventid is not correct. Got %s, expected %s", response.Result.Event, eid)
|
return fmt.Errorf("Eventid is not correct. Got %s, expected %s", response.Result.(*ctypes.ResultEvent).Event, eid)
|
||||||
}
|
}
|
||||||
tx := response.Result.Data.Tx.(*types.SendTx)
|
tx := response.Result.(*ctypes.ResultEvent).Data.(types.EventDataTx).Tx.(*types.SendTx)
|
||||||
if bytes.Compare(tx.Inputs[0].Address, user[0].Address) != 0 {
|
if !bytes.Equal(tx.Inputs[0].Address, user[0].Address) {
|
||||||
return fmt.Errorf("Senders do not match up! Got %x, expected %x", tx.Inputs[0].Address, user[0].Address)
|
return fmt.Errorf("Senders do not match up! Got %x, expected %x", tx.Inputs[0].Address, user[0].Address)
|
||||||
}
|
}
|
||||||
if tx.Inputs[0].Amount != amt {
|
if tx.Inputs[0].Amount != amt {
|
||||||
return fmt.Errorf("Amt does not match up! Got %d, expected %d", tx.Inputs[0].Amount, amt)
|
return fmt.Errorf("Amt does not match up! Got %d, expected %d", tx.Inputs[0].Amount, amt)
|
||||||
}
|
}
|
||||||
if bytes.Compare(tx.Outputs[0].Address, toAddr) != 0 {
|
if !bytes.Equal(tx.Outputs[0].Address, toAddr) {
|
||||||
return fmt.Errorf("Receivers do not match up! Got %x, expected %x", tx.Outputs[0].Address, user[0].Address)
|
return fmt.Errorf("Receivers do not match up! Got %x, expected %x", tx.Outputs[0].Address, user[0].Address)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func unmarshalValidateCall(amt int64, returnCode []byte) func(string, []byte) error {
|
func unmarshalValidateTx(amt int64, returnCode []byte) func(string, []byte) error {
|
||||||
return func(eid string, b []byte) error {
|
return func(eid string, b []byte) error {
|
||||||
// unmarshall and assert somethings
|
// unmarshall and assert somethings
|
||||||
var response struct {
|
var response ctypes.Response
|
||||||
JSONRPC string `json:"jsonrpc"`
|
|
||||||
Id string `json:"id"`
|
|
||||||
Result struct {
|
|
||||||
Event string `json:"event"`
|
|
||||||
Data struct {
|
|
||||||
Tx types.CallTx `json:"tx"`
|
|
||||||
Return []byte `json:"return"`
|
|
||||||
Exception string `json:"exception"`
|
|
||||||
} `json:"data"`
|
|
||||||
} `json:"result"`
|
|
||||||
Error string `json:"error"`
|
|
||||||
}
|
|
||||||
var err error
|
var err error
|
||||||
wire.ReadJSON(&response, b, &err)
|
wire.ReadJSON(&response, b, &err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -250,36 +223,31 @@ func unmarshalValidateCall(amt int64, returnCode []byte) func(string, []byte) er
|
|||||||
if response.Error != "" {
|
if response.Error != "" {
|
||||||
return fmt.Errorf(response.Error)
|
return fmt.Errorf(response.Error)
|
||||||
}
|
}
|
||||||
if response.Result.Data.Exception != "" {
|
var data = response.Result.(*ctypes.ResultEvent).Data.(types.EventDataTx)
|
||||||
return fmt.Errorf(response.Result.Data.Exception)
|
if data.Exception != "" {
|
||||||
|
return fmt.Errorf(data.Exception)
|
||||||
}
|
}
|
||||||
tx := response.Result.Data.Tx
|
tx := data.Tx.(*types.CallTx)
|
||||||
if bytes.Compare(tx.Input.Address, user[0].Address) != 0 {
|
if !bytes.Equal(tx.Input.Address, user[0].Address) {
|
||||||
return fmt.Errorf("Senders do not match up! Got %x, expected %x", tx.Input.Address, user[0].Address)
|
return fmt.Errorf("Senders do not match up! Got %x, expected %x",
|
||||||
|
tx.Input.Address, user[0].Address)
|
||||||
}
|
}
|
||||||
if tx.Input.Amount != amt {
|
if tx.Input.Amount != amt {
|
||||||
return fmt.Errorf("Amt does not match up! Got %d, expected %d", tx.Input.Amount, amt)
|
return fmt.Errorf("Amt does not match up! Got %d, expected %d",
|
||||||
|
tx.Input.Amount, amt)
|
||||||
}
|
}
|
||||||
ret := response.Result.Data.Return
|
ret := data.Return
|
||||||
if bytes.Compare(ret, returnCode) != 0 {
|
if !bytes.Equal(ret, returnCode) {
|
||||||
return fmt.Errorf("Call did not return correctly. Got %x, expected %x", ret, returnCode)
|
return fmt.Errorf("Tx did not return correctly. Got %x, expected %x", ret, returnCode)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func unmarshalValidateCallCall(origin, returnCode []byte, txid *[]byte) func(string, []byte) error {
|
func unmarshalValidateCall(origin, returnCode []byte, txid *[]byte) func(string, []byte) error {
|
||||||
return func(eid string, b []byte) error {
|
return func(eid string, b []byte) error {
|
||||||
// unmarshall and assert somethings
|
// unmarshall and assert somethings
|
||||||
var response struct {
|
var response ctypes.Response
|
||||||
JSONRPC string `json:"jsonrpc"`
|
|
||||||
Id string `json:"id"`
|
|
||||||
Result struct {
|
|
||||||
Event string `json:"event"`
|
|
||||||
Data types.EventMsgCall `json:"data"`
|
|
||||||
} `json:"result"`
|
|
||||||
Error string `json:"error"`
|
|
||||||
}
|
|
||||||
var err error
|
var err error
|
||||||
wire.ReadJSON(&response, b, &err)
|
wire.ReadJSON(&response, b, &err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -288,18 +256,21 @@ func unmarshalValidateCallCall(origin, returnCode []byte, txid *[]byte) func(str
|
|||||||
if response.Error != "" {
|
if response.Error != "" {
|
||||||
return fmt.Errorf(response.Error)
|
return fmt.Errorf(response.Error)
|
||||||
}
|
}
|
||||||
if response.Result.Data.Exception != "" {
|
var data = response.Result.(*ctypes.ResultEvent).Data.(types.EventDataCall)
|
||||||
return fmt.Errorf(response.Result.Data.Exception)
|
if data.Exception != "" {
|
||||||
|
return fmt.Errorf(data.Exception)
|
||||||
}
|
}
|
||||||
if bytes.Compare(response.Result.Data.Origin, origin) != 0 {
|
if !bytes.Equal(data.Origin, origin) {
|
||||||
return fmt.Errorf("Origin does not match up! Got %x, expected %x", response.Result.Data.Origin, origin)
|
return fmt.Errorf("Origin does not match up! Got %x, expected %x",
|
||||||
|
data.Origin, origin)
|
||||||
}
|
}
|
||||||
ret := response.Result.Data.Return
|
ret := data.Return
|
||||||
if bytes.Compare(ret, returnCode) != 0 {
|
if !bytes.Equal(ret, returnCode) {
|
||||||
return fmt.Errorf("Call did not return correctly. Got %x, expected %x", ret, returnCode)
|
return fmt.Errorf("Call did not return correctly. Got %x, expected %x", ret, returnCode)
|
||||||
}
|
}
|
||||||
if bytes.Compare(response.Result.Data.TxID, *txid) != 0 {
|
if !bytes.Equal(data.TxID, *txid) {
|
||||||
return fmt.Errorf("TxIDs do not match up! Got %x, expected %x", response.Result.Data.TxID, *txid)
|
return fmt.Errorf("TxIDs do not match up! Got %x, expected %x",
|
||||||
|
data.TxID, *txid)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,3 @@ func NewRPCResponse(id string, res interface{}, err string) RPCResponse {
|
|||||||
Error: err,
|
Error: err,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Goes in the Result field of an RPCResponse.
|
|
||||||
type RPCEventResult struct {
|
|
||||||
Event string `json:"event"`
|
|
||||||
Data interface{} `json:"data"`
|
|
||||||
}
|
|
||||||
|
@ -101,8 +101,8 @@ func execBlock(s *State, block *types.Block, blockPartsHeader types.PartSetHeade
|
|||||||
|
|
||||||
// If any unbonding periods are over,
|
// If any unbonding periods are over,
|
||||||
// reward account with bonded coins.
|
// reward account with bonded coins.
|
||||||
toRelease := []*Validator{}
|
toRelease := []*types.Validator{}
|
||||||
s.UnbondingValidators.Iterate(func(index int, val *Validator) bool {
|
s.UnbondingValidators.Iterate(func(index int, val *types.Validator) bool {
|
||||||
if val.UnbondHeight+unbondingPeriodBlocks < block.Height {
|
if val.UnbondHeight+unbondingPeriodBlocks < block.Height {
|
||||||
toRelease = append(toRelease, val)
|
toRelease = append(toRelease, val)
|
||||||
}
|
}
|
||||||
@ -114,8 +114,8 @@ func execBlock(s *State, block *types.Block, blockPartsHeader types.PartSetHeade
|
|||||||
|
|
||||||
// If any validators haven't signed in a while,
|
// If any validators haven't signed in a while,
|
||||||
// unbond them, they have timed out.
|
// unbond them, they have timed out.
|
||||||
toTimeout := []*Validator{}
|
toTimeout := []*types.Validator{}
|
||||||
s.BondedValidators.Iterate(func(index int, val *Validator) bool {
|
s.BondedValidators.Iterate(func(index int, val *types.Validator) bool {
|
||||||
lastActivityHeight := MaxInt(val.BondHeight, val.LastCommitHeight)
|
lastActivityHeight := MaxInt(val.BondHeight, val.LastCommitHeight)
|
||||||
if lastActivityHeight+validatorTimeoutBlocks < block.Height {
|
if lastActivityHeight+validatorTimeoutBlocks < block.Height {
|
||||||
log.Notice("Validator timeout", "validator", val, "height", block.Height)
|
log.Notice("Validator timeout", "validator", val, "height", block.Height)
|
||||||
@ -337,11 +337,11 @@ func ExecTx(blockCache *BlockCache, tx types.Tx, runCall bool, evc events.Fireab
|
|||||||
// if the evc is nil, nothing will happen
|
// if the evc is nil, nothing will happen
|
||||||
if evc != nil {
|
if evc != nil {
|
||||||
for _, i := range tx.Inputs {
|
for _, i := range tx.Inputs {
|
||||||
evc.FireEvent(types.EventStringAccInput(i.Address), types.EventMsgTx{tx, nil, ""})
|
evc.FireEvent(types.EventStringAccInput(i.Address), types.EventDataTx{tx, nil, ""})
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, o := range tx.Outputs {
|
for _, o := range tx.Outputs {
|
||||||
evc.FireEvent(types.EventStringAccOutput(o.Address), types.EventMsgTx{tx, nil, ""})
|
evc.FireEvent(types.EventStringAccOutput(o.Address), types.EventDataTx{tx, nil, ""})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -494,8 +494,8 @@ func ExecTx(blockCache *BlockCache, tx types.Tx, runCall bool, evc events.Fireab
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
exception = err.Error()
|
exception = err.Error()
|
||||||
}
|
}
|
||||||
evc.FireEvent(types.EventStringAccInput(tx.Input.Address), types.EventMsgTx{tx, ret, exception})
|
evc.FireEvent(types.EventStringAccInput(tx.Input.Address), types.EventDataTx{tx, ret, exception})
|
||||||
evc.FireEvent(types.EventStringAccOutput(tx.Address), types.EventMsgTx{tx, ret, exception})
|
evc.FireEvent(types.EventStringAccOutput(tx.Address), types.EventDataTx{tx, ret, exception})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// The mempool does not call txs until
|
// The mempool does not call txs until
|
||||||
@ -691,7 +691,7 @@ func ExecTx(blockCache *BlockCache, tx types.Tx, runCall bool, evc events.Fireab
|
|||||||
blockCache.UpdateAccount(acc)
|
blockCache.UpdateAccount(acc)
|
||||||
}
|
}
|
||||||
// Add ValidatorInfo
|
// Add ValidatorInfo
|
||||||
_s.SetValidatorInfo(&ValidatorInfo{
|
_s.SetValidatorInfo(&types.ValidatorInfo{
|
||||||
Address: tx.PubKey.Address(),
|
Address: tx.PubKey.Address(),
|
||||||
PubKey: tx.PubKey,
|
PubKey: tx.PubKey,
|
||||||
UnbondTo: tx.UnbondTo,
|
UnbondTo: tx.UnbondTo,
|
||||||
@ -699,7 +699,7 @@ func ExecTx(blockCache *BlockCache, tx types.Tx, runCall bool, evc events.Fireab
|
|||||||
FirstBondAmount: outTotal,
|
FirstBondAmount: outTotal,
|
||||||
})
|
})
|
||||||
// Add Validator
|
// Add Validator
|
||||||
added := _s.BondedValidators.Add(&Validator{
|
added := _s.BondedValidators.Add(&types.Validator{
|
||||||
Address: tx.PubKey.Address(),
|
Address: tx.PubKey.Address(),
|
||||||
PubKey: tx.PubKey,
|
PubKey: tx.PubKey,
|
||||||
BondHeight: _s.LastBlockHeight + 1,
|
BondHeight: _s.LastBlockHeight + 1,
|
||||||
@ -893,7 +893,7 @@ func ExecTx(blockCache *BlockCache, tx types.Tx, runCall bool, evc events.Fireab
|
|||||||
}
|
}
|
||||||
|
|
||||||
if evc != nil {
|
if evc != nil {
|
||||||
evc.FireEvent(types.EventStringAccInput(tx.Input.Address), types.EventMsgTx{tx, nil, ""})
|
evc.FireEvent(types.EventStringAccInput(tx.Input.Address), types.EventDataTx{tx, nil, ""})
|
||||||
evc.FireEvent(types.EventStringPermissions(ptypes.PermFlagToString(permFlag)), tx)
|
evc.FireEvent(types.EventStringPermissions(ptypes.PermFlagToString(permFlag)), tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -981,3 +981,14 @@ func hasBondOrSendPermission(state AccountGetter, accs map[string]*acm.Account)
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type InvalidTxError struct {
|
||||||
|
Tx types.Tx
|
||||||
|
Reason error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (txErr InvalidTxError) Error() string {
|
||||||
|
return Fmt("Invalid tx: [%v] reason: [%v]", txErr.Tx, txErr.Reason)
|
||||||
|
}
|
||||||
|
175
state/genesis.go
175
state/genesis.go
@ -1,175 +0,0 @@
|
|||||||
package state
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
acm "github.com/tendermint/tendermint/account"
|
|
||||||
. "github.com/tendermint/tendermint/common"
|
|
||||||
dbm "github.com/tendermint/tendermint/db"
|
|
||||||
"github.com/tendermint/tendermint/merkle"
|
|
||||||
ptypes "github.com/tendermint/tendermint/permission/types"
|
|
||||||
"github.com/tendermint/tendermint/types"
|
|
||||||
"github.com/tendermint/tendermint/wire"
|
|
||||||
)
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// we store the gendoc in the db
|
|
||||||
|
|
||||||
var GenDocKey = []byte("GenDocKey")
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// core types for a genesis definition
|
|
||||||
|
|
||||||
type BasicAccount struct {
|
|
||||||
Address []byte `json:"address"`
|
|
||||||
Amount int64 `json:"amount"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type GenesisAccount struct {
|
|
||||||
Address []byte `json:"address"`
|
|
||||||
Amount int64 `json:"amount"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Permissions *ptypes.AccountPermissions `json:"permissions"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type GenesisValidator struct {
|
|
||||||
PubKey acm.PubKeyEd25519 `json:"pub_key"`
|
|
||||||
Amount int64 `json:"amount"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
UnbondTo []BasicAccount `json:"unbond_to"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type GenesisParams struct {
|
|
||||||
GlobalPermissions *ptypes.AccountPermissions `json:"global_permissions"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type GenesisDoc struct {
|
|
||||||
GenesisTime time.Time `json:"genesis_time"`
|
|
||||||
ChainID string `json:"chain_id"`
|
|
||||||
Params *GenesisParams `json:"params"`
|
|
||||||
Accounts []GenesisAccount `json:"accounts"`
|
|
||||||
Validators []GenesisValidator `json:"validators"`
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
|
||||||
// Make genesis state from file
|
|
||||||
|
|
||||||
func GenesisDocFromJSON(jsonBlob []byte) (genState *GenesisDoc) {
|
|
||||||
var err error
|
|
||||||
wire.ReadJSONPtr(&genState, jsonBlob, &err)
|
|
||||||
if err != nil {
|
|
||||||
Exit(Fmt("Couldn't read GenesisDoc: %v", err))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func MakeGenesisStateFromFile(db dbm.DB, genDocFile string) (*GenesisDoc, *State) {
|
|
||||||
jsonBlob, err := ioutil.ReadFile(genDocFile)
|
|
||||||
if err != nil {
|
|
||||||
Exit(Fmt("Couldn't read GenesisDoc file: %v", err))
|
|
||||||
}
|
|
||||||
genDoc := GenesisDocFromJSON(jsonBlob)
|
|
||||||
return genDoc, MakeGenesisState(db, genDoc)
|
|
||||||
}
|
|
||||||
|
|
||||||
func MakeGenesisState(db dbm.DB, genDoc *GenesisDoc) *State {
|
|
||||||
if len(genDoc.Validators) == 0 {
|
|
||||||
Exit(Fmt("The genesis file has no validators"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if genDoc.GenesisTime.IsZero() {
|
|
||||||
genDoc.GenesisTime = time.Now()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make accounts state tree
|
|
||||||
accounts := merkle.NewIAVLTree(wire.BasicCodec, acm.AccountCodec, defaultAccountsCacheCapacity, db)
|
|
||||||
for _, genAcc := range genDoc.Accounts {
|
|
||||||
perm := ptypes.ZeroAccountPermissions
|
|
||||||
if genAcc.Permissions != nil {
|
|
||||||
perm = *genAcc.Permissions
|
|
||||||
}
|
|
||||||
acc := &acm.Account{
|
|
||||||
Address: genAcc.Address,
|
|
||||||
PubKey: nil,
|
|
||||||
Sequence: 0,
|
|
||||||
Balance: genAcc.Amount,
|
|
||||||
Permissions: perm,
|
|
||||||
}
|
|
||||||
accounts.Set(acc.Address, acc)
|
|
||||||
}
|
|
||||||
|
|
||||||
// global permissions are saved as the 0 address
|
|
||||||
// so they are included in the accounts tree
|
|
||||||
globalPerms := ptypes.DefaultAccountPermissions
|
|
||||||
if genDoc.Params != nil && genDoc.Params.GlobalPermissions != nil {
|
|
||||||
globalPerms = *genDoc.Params.GlobalPermissions
|
|
||||||
// XXX: make sure the set bits are all true
|
|
||||||
// Without it the HasPermission() functions will fail
|
|
||||||
globalPerms.Base.SetBit = ptypes.AllPermFlags
|
|
||||||
}
|
|
||||||
|
|
||||||
permsAcc := &acm.Account{
|
|
||||||
Address: ptypes.GlobalPermissionsAddress,
|
|
||||||
PubKey: nil,
|
|
||||||
Sequence: 0,
|
|
||||||
Balance: 1337,
|
|
||||||
Permissions: globalPerms,
|
|
||||||
}
|
|
||||||
accounts.Set(permsAcc.Address, permsAcc)
|
|
||||||
|
|
||||||
// Make validatorInfos state tree && validators slice
|
|
||||||
validatorInfos := merkle.NewIAVLTree(wire.BasicCodec, ValidatorInfoCodec, 0, db)
|
|
||||||
validators := make([]*Validator, len(genDoc.Validators))
|
|
||||||
for i, val := range genDoc.Validators {
|
|
||||||
pubKey := val.PubKey
|
|
||||||
address := pubKey.Address()
|
|
||||||
|
|
||||||
// Make ValidatorInfo
|
|
||||||
valInfo := &ValidatorInfo{
|
|
||||||
Address: address,
|
|
||||||
PubKey: pubKey,
|
|
||||||
UnbondTo: make([]*types.TxOutput, len(val.UnbondTo)),
|
|
||||||
FirstBondHeight: 0,
|
|
||||||
FirstBondAmount: val.Amount,
|
|
||||||
}
|
|
||||||
for i, unbondTo := range val.UnbondTo {
|
|
||||||
valInfo.UnbondTo[i] = &types.TxOutput{
|
|
||||||
Address: unbondTo.Address,
|
|
||||||
Amount: unbondTo.Amount,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
validatorInfos.Set(address, valInfo)
|
|
||||||
|
|
||||||
// Make validator
|
|
||||||
validators[i] = &Validator{
|
|
||||||
Address: address,
|
|
||||||
PubKey: pubKey,
|
|
||||||
VotingPower: val.Amount,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make namereg tree
|
|
||||||
nameReg := merkle.NewIAVLTree(wire.BasicCodec, NameRegCodec, 0, db)
|
|
||||||
// TODO: add names, contracts to genesis.json
|
|
||||||
|
|
||||||
// IAVLTrees must be persisted before copy operations.
|
|
||||||
accounts.Save()
|
|
||||||
validatorInfos.Save()
|
|
||||||
nameReg.Save()
|
|
||||||
|
|
||||||
return &State{
|
|
||||||
DB: db,
|
|
||||||
ChainID: genDoc.ChainID,
|
|
||||||
LastBlockHeight: 0,
|
|
||||||
LastBlockHash: nil,
|
|
||||||
LastBlockParts: types.PartSetHeader{},
|
|
||||||
LastBlockTime: genDoc.GenesisTime,
|
|
||||||
BondedValidators: NewValidatorSet(validators),
|
|
||||||
LastBondedValidators: NewValidatorSet(nil),
|
|
||||||
UnbondingValidators: NewValidatorSet(nil),
|
|
||||||
accounts: accounts,
|
|
||||||
validatorInfos: validatorInfos,
|
|
||||||
nameReg: nameReg,
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
tdb "github.com/tendermint/tendermint/db"
|
tdb "github.com/tendermint/tendermint/db"
|
||||||
ptypes "github.com/tendermint/tendermint/permission/types"
|
ptypes "github.com/tendermint/tendermint/permission/types"
|
||||||
|
. "github.com/tendermint/tendermint/state/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
var chain_id = "lone_ranger"
|
var chain_id = "lone_ranger"
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
dbm "github.com/tendermint/tendermint/db"
|
dbm "github.com/tendermint/tendermint/db"
|
||||||
"github.com/tendermint/tendermint/events"
|
"github.com/tendermint/tendermint/events"
|
||||||
ptypes "github.com/tendermint/tendermint/permission/types"
|
ptypes "github.com/tendermint/tendermint/permission/types"
|
||||||
|
. "github.com/tendermint/tendermint/state/types"
|
||||||
"github.com/tendermint/tendermint/types"
|
"github.com/tendermint/tendermint/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1073,9 +1074,9 @@ func execTxWaitEvent(t *testing.T, blockCache *BlockCache, tx types.Tx, eventid
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch ev := msg.(type) {
|
switch ev := msg.(type) {
|
||||||
case types.EventMsgTx:
|
case types.EventDataTx:
|
||||||
return ev, ev.Exception
|
return ev, ev.Exception
|
||||||
case types.EventMsgCall:
|
case types.EventDataCall:
|
||||||
return ev, ev.Exception
|
return ev, ev.Exception
|
||||||
case string:
|
case string:
|
||||||
return nil, ev
|
return nil, ev
|
||||||
@ -1118,7 +1119,7 @@ func testSNativeCALL(t *testing.T, expectPass bool, blockCache *BlockCache, doug
|
|||||||
if exception != "" {
|
if exception != "" {
|
||||||
t.Fatal("Unexpected exception", exception)
|
t.Fatal("Unexpected exception", exception)
|
||||||
}
|
}
|
||||||
evv := ev.(types.EventMsgCall)
|
evv := ev.(types.EventDataCall)
|
||||||
ret := evv.Return
|
ret := evv.Return
|
||||||
if err := f(ret); err != nil {
|
if err := f(ret); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
145
state/state.go
145
state/state.go
@ -3,15 +3,18 @@ package state
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
acm "github.com/tendermint/tendermint/account"
|
acm "github.com/tendermint/tendermint/account"
|
||||||
"github.com/tendermint/tendermint/wire"
|
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
dbm "github.com/tendermint/tendermint/db"
|
dbm "github.com/tendermint/tendermint/db"
|
||||||
"github.com/tendermint/tendermint/events"
|
"github.com/tendermint/tendermint/events"
|
||||||
"github.com/tendermint/tendermint/merkle"
|
"github.com/tendermint/tendermint/merkle"
|
||||||
|
ptypes "github.com/tendermint/tendermint/permission/types"
|
||||||
|
. "github.com/tendermint/tendermint/state/types"
|
||||||
"github.com/tendermint/tendermint/types"
|
"github.com/tendermint/tendermint/types"
|
||||||
|
"github.com/tendermint/tendermint/wire"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -32,9 +35,9 @@ type State struct {
|
|||||||
LastBlockHash []byte
|
LastBlockHash []byte
|
||||||
LastBlockParts types.PartSetHeader
|
LastBlockParts types.PartSetHeader
|
||||||
LastBlockTime time.Time
|
LastBlockTime time.Time
|
||||||
BondedValidators *ValidatorSet
|
BondedValidators *types.ValidatorSet
|
||||||
LastBondedValidators *ValidatorSet
|
LastBondedValidators *types.ValidatorSet
|
||||||
UnbondingValidators *ValidatorSet
|
UnbondingValidators *types.ValidatorSet
|
||||||
accounts merkle.Tree // Shouldn't be accessed directly.
|
accounts merkle.Tree // Shouldn't be accessed directly.
|
||||||
validatorInfos merkle.Tree // Shouldn't be accessed directly.
|
validatorInfos merkle.Tree // Shouldn't be accessed directly.
|
||||||
nameReg merkle.Tree // Shouldn't be accessed directly.
|
nameReg merkle.Tree // Shouldn't be accessed directly.
|
||||||
@ -54,14 +57,14 @@ func LoadState(db dbm.DB) *State {
|
|||||||
s.LastBlockHash = wire.ReadByteSlice(r, n, err)
|
s.LastBlockHash = wire.ReadByteSlice(r, n, err)
|
||||||
s.LastBlockParts = wire.ReadBinary(types.PartSetHeader{}, r, n, err).(types.PartSetHeader)
|
s.LastBlockParts = wire.ReadBinary(types.PartSetHeader{}, r, n, err).(types.PartSetHeader)
|
||||||
s.LastBlockTime = wire.ReadTime(r, n, err)
|
s.LastBlockTime = wire.ReadTime(r, n, err)
|
||||||
s.BondedValidators = wire.ReadBinary(&ValidatorSet{}, r, n, err).(*ValidatorSet)
|
s.BondedValidators = wire.ReadBinary(&types.ValidatorSet{}, r, n, err).(*types.ValidatorSet)
|
||||||
s.LastBondedValidators = wire.ReadBinary(&ValidatorSet{}, r, n, err).(*ValidatorSet)
|
s.LastBondedValidators = wire.ReadBinary(&types.ValidatorSet{}, r, n, err).(*types.ValidatorSet)
|
||||||
s.UnbondingValidators = wire.ReadBinary(&ValidatorSet{}, r, n, err).(*ValidatorSet)
|
s.UnbondingValidators = wire.ReadBinary(&types.ValidatorSet{}, r, n, err).(*types.ValidatorSet)
|
||||||
accountsHash := wire.ReadByteSlice(r, n, err)
|
accountsHash := wire.ReadByteSlice(r, n, err)
|
||||||
s.accounts = merkle.NewIAVLTree(wire.BasicCodec, acm.AccountCodec, defaultAccountsCacheCapacity, db)
|
s.accounts = merkle.NewIAVLTree(wire.BasicCodec, acm.AccountCodec, defaultAccountsCacheCapacity, db)
|
||||||
s.accounts.Load(accountsHash)
|
s.accounts.Load(accountsHash)
|
||||||
validatorInfosHash := wire.ReadByteSlice(r, n, err)
|
validatorInfosHash := wire.ReadByteSlice(r, n, err)
|
||||||
s.validatorInfos = merkle.NewIAVLTree(wire.BasicCodec, ValidatorInfoCodec, 0, db)
|
s.validatorInfos = merkle.NewIAVLTree(wire.BasicCodec, types.ValidatorInfoCodec, 0, db)
|
||||||
s.validatorInfos.Load(validatorInfosHash)
|
s.validatorInfos.Load(validatorInfosHash)
|
||||||
nameRegHash := wire.ReadByteSlice(r, n, err)
|
nameRegHash := wire.ReadByteSlice(r, n, err)
|
||||||
s.nameReg = merkle.NewIAVLTree(wire.BasicCodec, NameRegCodec, 0, db)
|
s.nameReg = merkle.NewIAVLTree(wire.BasicCodec, NameRegCodec, 0, db)
|
||||||
@ -200,18 +203,18 @@ func (s *State) SetAccounts(accounts merkle.Tree) {
|
|||||||
|
|
||||||
// The returned ValidatorInfo is a copy, so mutating it
|
// The returned ValidatorInfo is a copy, so mutating it
|
||||||
// has no side effects.
|
// has no side effects.
|
||||||
func (s *State) GetValidatorInfo(address []byte) *ValidatorInfo {
|
func (s *State) GetValidatorInfo(address []byte) *types.ValidatorInfo {
|
||||||
_, valInfo := s.validatorInfos.Get(address)
|
_, valInfo := s.validatorInfos.Get(address)
|
||||||
if valInfo == nil {
|
if valInfo == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return valInfo.(*ValidatorInfo).Copy()
|
return valInfo.(*types.ValidatorInfo).Copy()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns false if new, true if updated.
|
// Returns false if new, true if updated.
|
||||||
// The valInfo is copied before setting, so mutating it
|
// The valInfo is copied before setting, so mutating it
|
||||||
// afterwards has no side effects.
|
// afterwards has no side effects.
|
||||||
func (s *State) SetValidatorInfo(valInfo *ValidatorInfo) (updated bool) {
|
func (s *State) SetValidatorInfo(valInfo *types.ValidatorInfo) (updated bool) {
|
||||||
return s.validatorInfos.Set(valInfo.Address, valInfo.Copy())
|
return s.validatorInfos.Set(valInfo.Address, valInfo.Copy())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,7 +222,7 @@ func (s *State) GetValidatorInfos() merkle.Tree {
|
|||||||
return s.validatorInfos.Copy()
|
return s.validatorInfos.Copy()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) unbondValidator(val *Validator) {
|
func (s *State) unbondValidator(val *types.Validator) {
|
||||||
// Move validator to UnbondingValidators
|
// Move validator to UnbondingValidators
|
||||||
val, removed := s.BondedValidators.Remove(val.Address)
|
val, removed := s.BondedValidators.Remove(val.Address)
|
||||||
if !removed {
|
if !removed {
|
||||||
@ -232,7 +235,7 @@ func (s *State) unbondValidator(val *Validator) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) rebondValidator(val *Validator) {
|
func (s *State) rebondValidator(val *types.Validator) {
|
||||||
// Move validator to BondingValidators
|
// Move validator to BondingValidators
|
||||||
val, removed := s.UnbondingValidators.Remove(val.Address)
|
val, removed := s.UnbondingValidators.Remove(val.Address)
|
||||||
if !removed {
|
if !removed {
|
||||||
@ -245,7 +248,7 @@ func (s *State) rebondValidator(val *Validator) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) releaseValidator(val *Validator) {
|
func (s *State) releaseValidator(val *types.Validator) {
|
||||||
// Update validatorInfo
|
// Update validatorInfo
|
||||||
valInfo := s.GetValidatorInfo(val.Address)
|
valInfo := s.GetValidatorInfo(val.Address)
|
||||||
if valInfo == nil {
|
if valInfo == nil {
|
||||||
@ -271,7 +274,7 @@ func (s *State) releaseValidator(val *Validator) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *State) destroyValidator(val *Validator) {
|
func (s *State) destroyValidator(val *types.Validator) {
|
||||||
// Update validatorInfo
|
// Update validatorInfo
|
||||||
valInfo := s.GetValidatorInfo(val.Address)
|
valInfo := s.GetValidatorInfo(val.Address)
|
||||||
if valInfo == nil {
|
if valInfo == nil {
|
||||||
@ -360,12 +363,114 @@ func (s *State) SetFireable(evc events.Fireable) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
// Genesis
|
||||||
|
|
||||||
type InvalidTxError struct {
|
func MakeGenesisStateFromFile(db dbm.DB, genDocFile string) (*GenesisDoc, *State) {
|
||||||
Tx types.Tx
|
jsonBlob, err := ioutil.ReadFile(genDocFile)
|
||||||
Reason error
|
if err != nil {
|
||||||
|
Exit(Fmt("Couldn't read GenesisDoc file: %v", err))
|
||||||
|
}
|
||||||
|
genDoc := GenesisDocFromJSON(jsonBlob)
|
||||||
|
return genDoc, MakeGenesisState(db, genDoc)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (txErr InvalidTxError) Error() string {
|
func MakeGenesisState(db dbm.DB, genDoc *GenesisDoc) *State {
|
||||||
return Fmt("Invalid tx: [%v] reason: [%v]", txErr.Tx, txErr.Reason)
|
if len(genDoc.Validators) == 0 {
|
||||||
|
Exit(Fmt("The genesis file has no validators"))
|
||||||
|
}
|
||||||
|
|
||||||
|
if genDoc.GenesisTime.IsZero() {
|
||||||
|
genDoc.GenesisTime = time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make accounts state tree
|
||||||
|
accounts := merkle.NewIAVLTree(wire.BasicCodec, acm.AccountCodec, defaultAccountsCacheCapacity, db)
|
||||||
|
for _, genAcc := range genDoc.Accounts {
|
||||||
|
perm := ptypes.ZeroAccountPermissions
|
||||||
|
if genAcc.Permissions != nil {
|
||||||
|
perm = *genAcc.Permissions
|
||||||
|
}
|
||||||
|
acc := &acm.Account{
|
||||||
|
Address: genAcc.Address,
|
||||||
|
PubKey: nil,
|
||||||
|
Sequence: 0,
|
||||||
|
Balance: genAcc.Amount,
|
||||||
|
Permissions: perm,
|
||||||
|
}
|
||||||
|
accounts.Set(acc.Address, acc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// global permissions are saved as the 0 address
|
||||||
|
// so they are included in the accounts tree
|
||||||
|
globalPerms := ptypes.DefaultAccountPermissions
|
||||||
|
if genDoc.Params != nil && genDoc.Params.GlobalPermissions != nil {
|
||||||
|
globalPerms = *genDoc.Params.GlobalPermissions
|
||||||
|
// XXX: make sure the set bits are all true
|
||||||
|
// Without it the HasPermission() functions will fail
|
||||||
|
globalPerms.Base.SetBit = ptypes.AllPermFlags
|
||||||
|
}
|
||||||
|
|
||||||
|
permsAcc := &acm.Account{
|
||||||
|
Address: ptypes.GlobalPermissionsAddress,
|
||||||
|
PubKey: nil,
|
||||||
|
Sequence: 0,
|
||||||
|
Balance: 1337,
|
||||||
|
Permissions: globalPerms,
|
||||||
|
}
|
||||||
|
accounts.Set(permsAcc.Address, permsAcc)
|
||||||
|
|
||||||
|
// Make validatorInfos state tree && validators slice
|
||||||
|
validatorInfos := merkle.NewIAVLTree(wire.BasicCodec, types.ValidatorInfoCodec, 0, db)
|
||||||
|
validators := make([]*types.Validator, len(genDoc.Validators))
|
||||||
|
for i, val := range genDoc.Validators {
|
||||||
|
pubKey := val.PubKey
|
||||||
|
address := pubKey.Address()
|
||||||
|
|
||||||
|
// Make ValidatorInfo
|
||||||
|
valInfo := &types.ValidatorInfo{
|
||||||
|
Address: address,
|
||||||
|
PubKey: pubKey,
|
||||||
|
UnbondTo: make([]*types.TxOutput, len(val.UnbondTo)),
|
||||||
|
FirstBondHeight: 0,
|
||||||
|
FirstBondAmount: val.Amount,
|
||||||
|
}
|
||||||
|
for i, unbondTo := range val.UnbondTo {
|
||||||
|
valInfo.UnbondTo[i] = &types.TxOutput{
|
||||||
|
Address: unbondTo.Address,
|
||||||
|
Amount: unbondTo.Amount,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
validatorInfos.Set(address, valInfo)
|
||||||
|
|
||||||
|
// Make validator
|
||||||
|
validators[i] = &types.Validator{
|
||||||
|
Address: address,
|
||||||
|
PubKey: pubKey,
|
||||||
|
VotingPower: val.Amount,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make namereg tree
|
||||||
|
nameReg := merkle.NewIAVLTree(wire.BasicCodec, NameRegCodec, 0, db)
|
||||||
|
// TODO: add names, contracts to genesis.json
|
||||||
|
|
||||||
|
// IAVLTrees must be persisted before copy operations.
|
||||||
|
accounts.Save()
|
||||||
|
validatorInfos.Save()
|
||||||
|
nameReg.Save()
|
||||||
|
|
||||||
|
return &State{
|
||||||
|
DB: db,
|
||||||
|
ChainID: genDoc.ChainID,
|
||||||
|
LastBlockHeight: 0,
|
||||||
|
LastBlockHash: nil,
|
||||||
|
LastBlockParts: types.PartSetHeader{},
|
||||||
|
LastBlockTime: genDoc.GenesisTime,
|
||||||
|
BondedValidators: types.NewValidatorSet(validators),
|
||||||
|
LastBondedValidators: types.NewValidatorSet(nil),
|
||||||
|
UnbondingValidators: types.NewValidatorSet(nil),
|
||||||
|
accounts: accounts,
|
||||||
|
validatorInfos: validatorInfos,
|
||||||
|
nameReg: nameReg,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,28 +1,17 @@
|
|||||||
package state
|
package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"sort"
|
"sort"
|
||||||
|
"time"
|
||||||
|
|
||||||
acm "github.com/tendermint/tendermint/account"
|
acm "github.com/tendermint/tendermint/account"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
dbm "github.com/tendermint/tendermint/db"
|
dbm "github.com/tendermint/tendermint/db"
|
||||||
ptypes "github.com/tendermint/tendermint/permission/types"
|
ptypes "github.com/tendermint/tendermint/permission/types"
|
||||||
|
. "github.com/tendermint/tendermint/state/types"
|
||||||
"github.com/tendermint/tendermint/types"
|
"github.com/tendermint/tendermint/types"
|
||||||
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Tempfile(prefix string) (*os.File, string) {
|
|
||||||
file, err := ioutil.TempFile("", prefix)
|
|
||||||
if err != nil {
|
|
||||||
PanicCrisis(err)
|
|
||||||
}
|
|
||||||
return file, file.Name()
|
|
||||||
}
|
|
||||||
|
|
||||||
func RandAccount(randBalance bool, minBalance int64) (*acm.Account, *acm.PrivAccount) {
|
func RandAccount(randBalance bool, minBalance int64) (*acm.Account, *acm.PrivAccount) {
|
||||||
privAccount := acm.GenPrivAccount()
|
privAccount := acm.GenPrivAccount()
|
||||||
perms := ptypes.DefaultAccountPermissions
|
perms := ptypes.DefaultAccountPermissions
|
||||||
@ -39,37 +28,7 @@ func RandAccount(randBalance bool, minBalance int64) (*acm.Account, *acm.PrivAcc
|
|||||||
return acc, privAccount
|
return acc, privAccount
|
||||||
}
|
}
|
||||||
|
|
||||||
func RandValidator(randBonded bool, minBonded int64) (*ValidatorInfo, *Validator, *PrivValidator) {
|
func RandGenesisDoc(numAccounts int, randBalance bool, minBalance int64, numValidators int, randBonded bool, minBonded int64) (*GenesisDoc, []*acm.PrivAccount, []*types.PrivValidator) {
|
||||||
privVal := GenPrivValidator()
|
|
||||||
_, tempFilePath := Tempfile("priv_validator_")
|
|
||||||
privVal.SetFile(tempFilePath)
|
|
||||||
bonded := minBonded
|
|
||||||
if randBonded {
|
|
||||||
bonded += int64(RandUint32())
|
|
||||||
}
|
|
||||||
valInfo := &ValidatorInfo{
|
|
||||||
Address: privVal.Address,
|
|
||||||
PubKey: privVal.PubKey,
|
|
||||||
UnbondTo: []*types.TxOutput{&types.TxOutput{
|
|
||||||
Amount: bonded,
|
|
||||||
Address: privVal.Address,
|
|
||||||
}},
|
|
||||||
FirstBondHeight: 0,
|
|
||||||
FirstBondAmount: bonded,
|
|
||||||
}
|
|
||||||
val := &Validator{
|
|
||||||
Address: valInfo.Address,
|
|
||||||
PubKey: valInfo.PubKey,
|
|
||||||
BondHeight: 0,
|
|
||||||
UnbondHeight: 0,
|
|
||||||
LastCommitHeight: 0,
|
|
||||||
VotingPower: valInfo.FirstBondAmount,
|
|
||||||
Accum: 0,
|
|
||||||
}
|
|
||||||
return valInfo, val, privVal
|
|
||||||
}
|
|
||||||
|
|
||||||
func RandGenesisDoc(numAccounts int, randBalance bool, minBalance int64, numValidators int, randBonded bool, minBonded int64) (*GenesisDoc, []*acm.PrivAccount, []*PrivValidator) {
|
|
||||||
accounts := make([]GenesisAccount, numAccounts)
|
accounts := make([]GenesisAccount, numAccounts)
|
||||||
privAccounts := make([]*acm.PrivAccount, numAccounts)
|
privAccounts := make([]*acm.PrivAccount, numAccounts)
|
||||||
defaultPerms := ptypes.DefaultAccountPermissions
|
defaultPerms := ptypes.DefaultAccountPermissions
|
||||||
@ -83,9 +42,9 @@ func RandGenesisDoc(numAccounts int, randBalance bool, minBalance int64, numVali
|
|||||||
privAccounts[i] = privAccount
|
privAccounts[i] = privAccount
|
||||||
}
|
}
|
||||||
validators := make([]GenesisValidator, numValidators)
|
validators := make([]GenesisValidator, numValidators)
|
||||||
privValidators := make([]*PrivValidator, numValidators)
|
privValidators := make([]*types.PrivValidator, numValidators)
|
||||||
for i := 0; i < numValidators; i++ {
|
for i := 0; i < numValidators; i++ {
|
||||||
valInfo, _, privVal := RandValidator(randBonded, minBonded)
|
valInfo, _, privVal := types.RandValidator(randBonded, minBonded)
|
||||||
validators[i] = GenesisValidator{
|
validators[i] = GenesisValidator{
|
||||||
PubKey: valInfo.PubKey,
|
PubKey: valInfo.PubKey,
|
||||||
Amount: valInfo.FirstBondAmount,
|
Amount: valInfo.FirstBondAmount,
|
||||||
@ -98,7 +57,7 @@ func RandGenesisDoc(numAccounts int, randBalance bool, minBalance int64, numVali
|
|||||||
}
|
}
|
||||||
privValidators[i] = privVal
|
privValidators[i] = privVal
|
||||||
}
|
}
|
||||||
sort.Sort(PrivValidatorsByAddress(privValidators))
|
sort.Sort(types.PrivValidatorsByAddress(privValidators))
|
||||||
return &GenesisDoc{
|
return &GenesisDoc{
|
||||||
GenesisTime: time.Now(),
|
GenesisTime: time.Now(),
|
||||||
ChainID: "tendermint_test",
|
ChainID: "tendermint_test",
|
||||||
@ -108,28 +67,10 @@ func RandGenesisDoc(numAccounts int, randBalance bool, minBalance int64, numVali
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func RandGenesisState(numAccounts int, randBalance bool, minBalance int64, numValidators int, randBonded bool, minBonded int64) (*State, []*acm.PrivAccount, []*PrivValidator) {
|
func RandGenesisState(numAccounts int, randBalance bool, minBalance int64, numValidators int, randBonded bool, minBonded int64) (*State, []*acm.PrivAccount, []*types.PrivValidator) {
|
||||||
db := dbm.NewMemDB()
|
db := dbm.NewMemDB()
|
||||||
genDoc, privAccounts, privValidators := RandGenesisDoc(numAccounts, randBalance, minBalance, numValidators, randBonded, minBonded)
|
genDoc, privAccounts, privValidators := RandGenesisDoc(numAccounts, randBalance, minBalance, numValidators, randBonded, minBonded)
|
||||||
s0 := MakeGenesisState(db, genDoc)
|
s0 := MakeGenesisState(db, genDoc)
|
||||||
s0.Save()
|
s0.Save()
|
||||||
return s0, privAccounts, privValidators
|
return s0, privAccounts, privValidators
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------
|
|
||||||
|
|
||||||
type PrivValidatorsByAddress []*PrivValidator
|
|
||||||
|
|
||||||
func (pvs PrivValidatorsByAddress) Len() int {
|
|
||||||
return len(pvs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pvs PrivValidatorsByAddress) Less(i, j int) bool {
|
|
||||||
return bytes.Compare(pvs[i].Address, pvs[j].Address) == -1
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pvs PrivValidatorsByAddress) Swap(i, j int) {
|
|
||||||
it := pvs[i]
|
|
||||||
pvs[i] = pvs[j]
|
|
||||||
pvs[j] = it
|
|
||||||
}
|
|
||||||
|
@ -12,7 +12,7 @@ type TxCache struct {
|
|||||||
backend *BlockCache
|
backend *BlockCache
|
||||||
accounts map[Word256]vmAccountInfo
|
accounts map[Word256]vmAccountInfo
|
||||||
storages map[Tuple256]Word256
|
storages map[Tuple256]Word256
|
||||||
logs []*vm.Log
|
logs []types.EventDataLog
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTxCache(backend *BlockCache) *TxCache {
|
func NewTxCache(backend *BlockCache) *TxCache {
|
||||||
@ -20,7 +20,7 @@ func NewTxCache(backend *BlockCache) *TxCache {
|
|||||||
backend: backend,
|
backend: backend,
|
||||||
accounts: make(map[Word256]vmAccountInfo),
|
accounts: make(map[Word256]vmAccountInfo),
|
||||||
storages: make(map[Tuple256]Word256),
|
storages: make(map[Tuple256]Word256),
|
||||||
logs: make([]*vm.Log, 0),
|
logs: make([]types.EventDataLog, 0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ func (cache *TxCache) Sync() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cache *TxCache) AddLog(log *vm.Log) {
|
func (cache *TxCache) AddLog(log types.EventDataLog) {
|
||||||
cache.logs = append(cache.logs, log)
|
cache.logs = append(cache.logs, log)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
61
state/types/genesis.go
Normal file
61
state/types/genesis.go
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
acm "github.com/tendermint/tendermint/account"
|
||||||
|
. "github.com/tendermint/tendermint/common"
|
||||||
|
ptypes "github.com/tendermint/tendermint/permission/types"
|
||||||
|
"github.com/tendermint/tendermint/wire"
|
||||||
|
)
|
||||||
|
|
||||||
|
//------------------------------------------------------------
|
||||||
|
// we store the gendoc in the db
|
||||||
|
|
||||||
|
var GenDocKey = []byte("GenDocKey")
|
||||||
|
|
||||||
|
//------------------------------------------------------------
|
||||||
|
// core types for a genesis definition
|
||||||
|
|
||||||
|
type BasicAccount struct {
|
||||||
|
Address []byte `json:"address"`
|
||||||
|
Amount int64 `json:"amount"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GenesisAccount struct {
|
||||||
|
Address []byte `json:"address"`
|
||||||
|
Amount int64 `json:"amount"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Permissions *ptypes.AccountPermissions `json:"permissions"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GenesisValidator struct {
|
||||||
|
PubKey acm.PubKeyEd25519 `json:"pub_key"`
|
||||||
|
Amount int64 `json:"amount"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
UnbondTo []BasicAccount `json:"unbond_to"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GenesisParams struct {
|
||||||
|
GlobalPermissions *ptypes.AccountPermissions `json:"global_permissions"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GenesisDoc struct {
|
||||||
|
GenesisTime time.Time `json:"genesis_time"`
|
||||||
|
ChainID string `json:"chain_id"`
|
||||||
|
Params *GenesisParams `json:"params"`
|
||||||
|
Accounts []GenesisAccount `json:"accounts"`
|
||||||
|
Validators []GenesisValidator `json:"validators"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------
|
||||||
|
// Make genesis state from file
|
||||||
|
|
||||||
|
func GenesisDocFromJSON(jsonBlob []byte) (genState *GenesisDoc) {
|
||||||
|
var err error
|
||||||
|
wire.ReadJSONPtr(&genState, jsonBlob, &err)
|
||||||
|
if err != nil {
|
||||||
|
Exit(Fmt("Couldn't read GenesisDoc: %v", err))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
@ -2,6 +2,9 @@ package types
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
. "github.com/tendermint/tendermint/common"
|
||||||
|
"github.com/tendermint/tendermint/wire"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Functions to generate eventId strings
|
// Functions to generate eventId strings
|
||||||
@ -18,15 +21,50 @@ func EventStringDupeout() string { return "Dupeout" }
|
|||||||
func EventStringNewBlock() string { return "NewBlock" }
|
func EventStringNewBlock() string { return "NewBlock" }
|
||||||
func EventStringFork() string { return "Fork" }
|
func EventStringFork() string { return "Fork" }
|
||||||
|
|
||||||
|
//----------------------------------------
|
||||||
|
|
||||||
|
const (
|
||||||
|
EventDataTypeNewBlock = byte(0x01)
|
||||||
|
EventDataTypeFork = byte(0x02)
|
||||||
|
EventDataTypeTx = byte(0x03)
|
||||||
|
EventDataTypeCall = byte(0x04)
|
||||||
|
EventDataTypeLog = byte(0x05)
|
||||||
|
)
|
||||||
|
|
||||||
|
type EventData interface{}
|
||||||
|
|
||||||
|
var _ = wire.RegisterInterface(
|
||||||
|
struct{ EventData }{},
|
||||||
|
wire.ConcreteType{EventDataNewBlock{}, EventDataTypeNewBlock},
|
||||||
|
// wire.ConcreteType{EventDataNewBlock{}, EventDataTypeFork },
|
||||||
|
wire.ConcreteType{EventDataTx{}, EventDataTypeTx},
|
||||||
|
wire.ConcreteType{EventDataCall{}, EventDataTypeCall},
|
||||||
|
wire.ConcreteType{EventDataLog{}, EventDataTypeLog},
|
||||||
|
)
|
||||||
|
|
||||||
// Most event messages are basic types (a block, a transaction)
|
// Most event messages are basic types (a block, a transaction)
|
||||||
// but some (an input to a call tx or a receive) are more exotic:
|
// but some (an input to a call tx or a receive) are more exotic:
|
||||||
|
|
||||||
type EventMsgTx struct {
|
type EventDataNewBlock struct {
|
||||||
|
Block *Block `json:"block"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// All txs fire EventDataTx, but only CallTx might have Return or Exception
|
||||||
|
type EventDataTx struct {
|
||||||
Tx Tx `json:"tx"`
|
Tx Tx `json:"tx"`
|
||||||
Return []byte `json:"return"`
|
Return []byte `json:"return"`
|
||||||
Exception string `json:"exception"`
|
Exception string `json:"exception"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EventDataCall fires when we call a contract, and when a contract calls another contract
|
||||||
|
type EventDataCall struct {
|
||||||
|
CallData *CallData `json:"call_data"`
|
||||||
|
Origin []byte `json:"origin"`
|
||||||
|
TxID []byte `json:"tx_id"`
|
||||||
|
Return []byte `json:"return"`
|
||||||
|
Exception string `json:"exception"`
|
||||||
|
}
|
||||||
|
|
||||||
type CallData struct {
|
type CallData struct {
|
||||||
Caller []byte `json:"caller"`
|
Caller []byte `json:"caller"`
|
||||||
Callee []byte `json:"callee"`
|
Callee []byte `json:"callee"`
|
||||||
@ -35,10 +73,10 @@ type CallData struct {
|
|||||||
Gas int64 `json:"gas"`
|
Gas int64 `json:"gas"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type EventMsgCall struct {
|
// EventDataLog fires when a contract executes the LOG opcode
|
||||||
CallData *CallData `json:"call_data"`
|
type EventDataLog struct {
|
||||||
Origin []byte `json:"origin"`
|
Address Word256 `json:"address"`
|
||||||
TxID []byte `json:"tx_id"`
|
Topics []Word256 `json:"topics"`
|
||||||
Return []byte `json:"return"`
|
Data []byte `json:"data"`
|
||||||
Exception string `json:"exception"`
|
Height int64 `json:"height"`
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package state
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@ -8,10 +9,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
acm "github.com/tendermint/tendermint/account"
|
acm "github.com/tendermint/tendermint/account"
|
||||||
"github.com/tendermint/tendermint/wire"
|
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
. "github.com/tendermint/tendermint/consensus/types"
|
"github.com/tendermint/tendermint/wire"
|
||||||
"github.com/tendermint/tendermint/types"
|
|
||||||
|
|
||||||
"github.com/tendermint/tendermint/Godeps/_workspace/src/github.com/tendermint/ed25519"
|
"github.com/tendermint/tendermint/Godeps/_workspace/src/github.com/tendermint/ed25519"
|
||||||
)
|
)
|
||||||
@ -23,11 +22,11 @@ const (
|
|||||||
stepPrecommit = 3
|
stepPrecommit = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
func voteToStep(vote *types.Vote) int8 {
|
func voteToStep(vote *Vote) int8 {
|
||||||
switch vote.Type {
|
switch vote.Type {
|
||||||
case types.VoteTypePrevote:
|
case VoteTypePrevote:
|
||||||
return stepPrevote
|
return stepPrevote
|
||||||
case types.VoteTypePrecommit:
|
case VoteTypePrecommit:
|
||||||
return stepPrecommit
|
return stepPrecommit
|
||||||
default:
|
default:
|
||||||
PanicSanity("Unknown vote type")
|
PanicSanity("Unknown vote type")
|
||||||
@ -104,7 +103,7 @@ func (privVal *PrivValidator) save() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (privVal *PrivValidator) SignVote(chainID string, vote *types.Vote) error {
|
func (privVal *PrivValidator) SignVote(chainID string, vote *Vote) error {
|
||||||
privVal.mtx.Lock()
|
privVal.mtx.Lock()
|
||||||
defer privVal.mtx.Unlock()
|
defer privVal.mtx.Unlock()
|
||||||
|
|
||||||
@ -135,7 +134,7 @@ func (privVal *PrivValidator) SignVote(chainID string, vote *types.Vote) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (privVal *PrivValidator) SignVoteUnsafe(chainID string, vote *types.Vote) {
|
func (privVal *PrivValidator) SignVoteUnsafe(chainID string, vote *Vote) {
|
||||||
vote.Signature = privVal.PrivKey.Sign(acm.SignBytes(chainID, vote)).(acm.SignatureEd25519)
|
vote.Signature = privVal.PrivKey.Sign(acm.SignBytes(chainID, vote)).(acm.SignatureEd25519)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +159,7 @@ func (privVal *PrivValidator) SignProposal(chainID string, proposal *Proposal) e
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (privVal *PrivValidator) SignRebondTx(chainID string, rebondTx *types.RebondTx) error {
|
func (privVal *PrivValidator) SignRebondTx(chainID string, rebondTx *RebondTx) error {
|
||||||
privVal.mtx.Lock()
|
privVal.mtx.Lock()
|
||||||
defer privVal.mtx.Unlock()
|
defer privVal.mtx.Unlock()
|
||||||
if privVal.LastHeight < rebondTx.Height {
|
if privVal.LastHeight < rebondTx.Height {
|
||||||
@ -183,3 +182,21 @@ func (privVal *PrivValidator) SignRebondTx(chainID string, rebondTx *types.Rebon
|
|||||||
func (privVal *PrivValidator) String() string {
|
func (privVal *PrivValidator) String() string {
|
||||||
return fmt.Sprintf("PrivValidator{%X LH:%v, LR:%v, LS:%v}", privVal.Address, privVal.LastHeight, privVal.LastRound, privVal.LastStep)
|
return fmt.Sprintf("PrivValidator{%X LH:%v, LR:%v, LS:%v}", privVal.Address, privVal.LastHeight, privVal.LastRound, privVal.LastStep)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-------------------------------------
|
||||||
|
|
||||||
|
type PrivValidatorsByAddress []*PrivValidator
|
||||||
|
|
||||||
|
func (pvs PrivValidatorsByAddress) Len() int {
|
||||||
|
return len(pvs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pvs PrivValidatorsByAddress) Less(i, j int) bool {
|
||||||
|
return bytes.Compare(pvs[i].Address, pvs[j].Address) == -1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pvs PrivValidatorsByAddress) Swap(i, j int) {
|
||||||
|
it := pvs[i]
|
||||||
|
pvs[i] = pvs[j]
|
||||||
|
pvs[j] = it
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package consensus
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
@ -6,9 +6,8 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
|
|
||||||
acm "github.com/tendermint/tendermint/account"
|
acm "github.com/tendermint/tendermint/account"
|
||||||
"github.com/tendermint/tendermint/wire"
|
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
"github.com/tendermint/tendermint/types"
|
"github.com/tendermint/tendermint/wire"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -19,12 +18,12 @@ var (
|
|||||||
type Proposal struct {
|
type Proposal struct {
|
||||||
Height int `json:"height"`
|
Height int `json:"height"`
|
||||||
Round int `json:"round"`
|
Round int `json:"round"`
|
||||||
BlockPartsHeader types.PartSetHeader `json:"block_parts_header"`
|
BlockPartsHeader PartSetHeader `json:"block_parts_header"`
|
||||||
POLRound int `json:"pol_round"` // -1 if null.
|
POLRound int `json:"pol_round"` // -1 if null.
|
||||||
Signature acm.SignatureEd25519 `json:"signature"`
|
Signature acm.SignatureEd25519 `json:"signature"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewProposal(height int, round int, blockPartsHeader types.PartSetHeader, polRound int) *Proposal {
|
func NewProposal(height int, round int, blockPartsHeader PartSetHeader, polRound int) *Proposal {
|
||||||
return &Proposal{
|
return &Proposal{
|
||||||
Height: height,
|
Height: height,
|
||||||
Round: round,
|
Round: round,
|
@ -1,4 +1,4 @@
|
|||||||
package consensus
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
@ -6,14 +6,13 @@ import (
|
|||||||
acm "github.com/tendermint/tendermint/account"
|
acm "github.com/tendermint/tendermint/account"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
_ "github.com/tendermint/tendermint/config/tendermint_test"
|
_ "github.com/tendermint/tendermint/config/tendermint_test"
|
||||||
"github.com/tendermint/tendermint/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestProposalSignable(t *testing.T) {
|
func TestProposalSignable(t *testing.T) {
|
||||||
proposal := &Proposal{
|
proposal := &Proposal{
|
||||||
Height: 12345,
|
Height: 12345,
|
||||||
Round: 23456,
|
Round: 23456,
|
||||||
BlockPartsHeader: types.PartSetHeader{111, []byte("blockparts")},
|
BlockPartsHeader: PartSetHeader{111, []byte("blockparts")},
|
||||||
POLRound: -1,
|
POLRound: -1,
|
||||||
}
|
}
|
||||||
signBytes := acm.SignBytes(config.GetString("chain_id"), proposal)
|
signBytes := acm.SignBytes(config.GetString("chain_id"), proposal)
|
@ -1,4 +1,4 @@
|
|||||||
package state
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@ -6,16 +6,15 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
|
|
||||||
acm "github.com/tendermint/tendermint/account"
|
acm "github.com/tendermint/tendermint/account"
|
||||||
"github.com/tendermint/tendermint/wire"
|
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
"github.com/tendermint/tendermint/types"
|
"github.com/tendermint/tendermint/wire"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Persistent (mostly) static data for each Validator
|
// Persistent (mostly) static data for each Validator
|
||||||
type ValidatorInfo struct {
|
type ValidatorInfo struct {
|
||||||
Address []byte `json:"address"`
|
Address []byte `json:"address"`
|
||||||
PubKey acm.PubKeyEd25519 `json:"pub_key"`
|
PubKey acm.PubKeyEd25519 `json:"pub_key"`
|
||||||
UnbondTo []*types.TxOutput `json:"unbond_to"`
|
UnbondTo []*TxOutput `json:"unbond_to"`
|
||||||
FirstBondHeight int `json:"first_bond_height"`
|
FirstBondHeight int `json:"first_bond_height"`
|
||||||
FirstBondAmount int64 `json:"first_bond_amount"`
|
FirstBondAmount int64 `json:"first_bond_amount"`
|
||||||
DestroyedHeight int `json:"destroyed_height"` // If destroyed
|
DestroyedHeight int `json:"destroyed_height"` // If destroyed
|
@ -1,4 +1,4 @@
|
|||||||
package state
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@ -9,7 +9,6 @@ import (
|
|||||||
"github.com/tendermint/tendermint/account"
|
"github.com/tendermint/tendermint/account"
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
"github.com/tendermint/tendermint/merkle"
|
"github.com/tendermint/tendermint/merkle"
|
||||||
"github.com/tendermint/tendermint/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ValidatorSet represent a set of *Validator at a given height.
|
// ValidatorSet represent a set of *Validator at a given height.
|
||||||
@ -204,7 +203,7 @@ func (valSet *ValidatorSet) Iterate(fn func(index int, val *Validator) bool) {
|
|||||||
|
|
||||||
// Verify that +2/3 of the set had signed the given signBytes
|
// Verify that +2/3 of the set had signed the given signBytes
|
||||||
func (valSet *ValidatorSet) VerifyValidation(chainID string,
|
func (valSet *ValidatorSet) VerifyValidation(chainID string,
|
||||||
hash []byte, parts types.PartSetHeader, height int, v *types.Validation) error {
|
hash []byte, parts PartSetHeader, height int, v *Validation) error {
|
||||||
if valSet.Size() != len(v.Precommits) {
|
if valSet.Size() != len(v.Precommits) {
|
||||||
return fmt.Errorf("Invalid validation -- wrong set size: %v vs %v", valSet.Size(), len(v.Precommits))
|
return fmt.Errorf("Invalid validation -- wrong set size: %v vs %v", valSet.Size(), len(v.Precommits))
|
||||||
}
|
}
|
||||||
@ -226,7 +225,7 @@ func (valSet *ValidatorSet) VerifyValidation(chainID string,
|
|||||||
if precommit.Round != round {
|
if precommit.Round != round {
|
||||||
return fmt.Errorf("Invalid validation -- wrong round: %v vs %v", round, precommit.Round)
|
return fmt.Errorf("Invalid validation -- wrong round: %v vs %v", round, precommit.Round)
|
||||||
}
|
}
|
||||||
if precommit.Type != types.VoteTypePrecommit {
|
if precommit.Type != VoteTypePrecommit {
|
||||||
return fmt.Errorf("Invalid validation -- not precommit @ index %v", idx)
|
return fmt.Errorf("Invalid validation -- not precommit @ index %v", idx)
|
||||||
}
|
}
|
||||||
_, val := valSet.GetByIndex(idx)
|
_, val := valSet.GetByIndex(idx)
|
@ -1,4 +1,4 @@
|
|||||||
package state
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/tendermint/tendermint/account"
|
"github.com/tendermint/tendermint/account"
|
@ -1,4 +1,4 @@
|
|||||||
package consensus
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@ -7,10 +7,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
acm "github.com/tendermint/tendermint/account"
|
acm "github.com/tendermint/tendermint/account"
|
||||||
"github.com/tendermint/tendermint/wire"
|
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
sm "github.com/tendermint/tendermint/state"
|
"github.com/tendermint/tendermint/wire"
|
||||||
"github.com/tendermint/tendermint/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// VoteSet helps collect signatures from validators at each height+round
|
// VoteSet helps collect signatures from validators at each height+round
|
||||||
@ -24,18 +22,18 @@ type VoteSet struct {
|
|||||||
type_ byte
|
type_ byte
|
||||||
|
|
||||||
mtx sync.Mutex
|
mtx sync.Mutex
|
||||||
valSet *sm.ValidatorSet
|
valSet *ValidatorSet
|
||||||
votes []*types.Vote // validator index -> vote
|
votes []*Vote // validator index -> vote
|
||||||
votesBitArray *BitArray // validator index -> has vote?
|
votesBitArray *BitArray // validator index -> has vote?
|
||||||
votesByBlock map[string]int64 // string(blockHash)+string(blockParts) -> vote sum.
|
votesByBlock map[string]int64 // string(blockHash)+string(blockParts) -> vote sum.
|
||||||
totalVotes int64
|
totalVotes int64
|
||||||
maj23Hash []byte
|
maj23Hash []byte
|
||||||
maj23Parts types.PartSetHeader
|
maj23Parts PartSetHeader
|
||||||
maj23Exists bool
|
maj23Exists bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructs a new VoteSet struct used to accumulate votes for given height/round.
|
// Constructs a new VoteSet struct used to accumulate votes for given height/round.
|
||||||
func NewVoteSet(height int, round int, type_ byte, valSet *sm.ValidatorSet) *VoteSet {
|
func NewVoteSet(height int, round int, type_ byte, valSet *ValidatorSet) *VoteSet {
|
||||||
if height == 0 {
|
if height == 0 {
|
||||||
PanicSanity("Cannot make VoteSet for height == 0, doesn't make sense.")
|
PanicSanity("Cannot make VoteSet for height == 0, doesn't make sense.")
|
||||||
}
|
}
|
||||||
@ -44,7 +42,7 @@ func NewVoteSet(height int, round int, type_ byte, valSet *sm.ValidatorSet) *Vot
|
|||||||
round: round,
|
round: round,
|
||||||
type_: type_,
|
type_: type_,
|
||||||
valSet: valSet,
|
valSet: valSet,
|
||||||
votes: make([]*types.Vote, valSet.Size()),
|
votes: make([]*Vote, valSet.Size()),
|
||||||
votesBitArray: NewBitArray(valSet.Size()),
|
votesBitArray: NewBitArray(valSet.Size()),
|
||||||
votesByBlock: make(map[string]int64),
|
votesByBlock: make(map[string]int64),
|
||||||
totalVotes: 0,
|
totalVotes: 0,
|
||||||
@ -87,7 +85,7 @@ func (voteSet *VoteSet) Size() int {
|
|||||||
// Otherwise returns err=ErrVote[UnexpectedStep|InvalidAccount|InvalidSignature|InvalidBlockHash|ConflictingSignature]
|
// Otherwise returns err=ErrVote[UnexpectedStep|InvalidAccount|InvalidSignature|InvalidBlockHash|ConflictingSignature]
|
||||||
// Duplicate votes return added=false, err=nil.
|
// Duplicate votes return added=false, err=nil.
|
||||||
// NOTE: vote should not be mutated after adding.
|
// NOTE: vote should not be mutated after adding.
|
||||||
func (voteSet *VoteSet) AddByIndex(valIndex int, vote *types.Vote) (added bool, index int, err error) {
|
func (voteSet *VoteSet) AddByIndex(valIndex int, vote *Vote) (added bool, index int, err error) {
|
||||||
voteSet.mtx.Lock()
|
voteSet.mtx.Lock()
|
||||||
defer voteSet.mtx.Unlock()
|
defer voteSet.mtx.Unlock()
|
||||||
|
|
||||||
@ -98,42 +96,42 @@ func (voteSet *VoteSet) AddByIndex(valIndex int, vote *types.Vote) (added bool,
|
|||||||
// Otherwise returns err=ErrVote[UnexpectedStep|InvalidAccount|InvalidSignature|InvalidBlockHash|ConflictingSignature]
|
// Otherwise returns err=ErrVote[UnexpectedStep|InvalidAccount|InvalidSignature|InvalidBlockHash|ConflictingSignature]
|
||||||
// Duplicate votes return added=false, err=nil.
|
// Duplicate votes return added=false, err=nil.
|
||||||
// NOTE: vote should not be mutated after adding.
|
// NOTE: vote should not be mutated after adding.
|
||||||
func (voteSet *VoteSet) AddByAddress(address []byte, vote *types.Vote) (added bool, index int, err error) {
|
func (voteSet *VoteSet) AddByAddress(address []byte, vote *Vote) (added bool, index int, err error) {
|
||||||
voteSet.mtx.Lock()
|
voteSet.mtx.Lock()
|
||||||
defer voteSet.mtx.Unlock()
|
defer voteSet.mtx.Unlock()
|
||||||
|
|
||||||
// Ensure that signer is a validator.
|
// Ensure that signer is a validator.
|
||||||
valIndex, val := voteSet.valSet.GetByAddress(address)
|
valIndex, val := voteSet.valSet.GetByAddress(address)
|
||||||
if val == nil {
|
if val == nil {
|
||||||
return false, 0, types.ErrVoteInvalidAccount
|
return false, 0, ErrVoteInvalidAccount
|
||||||
}
|
}
|
||||||
|
|
||||||
return voteSet.addVote(val, valIndex, vote)
|
return voteSet.addVote(val, valIndex, vote)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (voteSet *VoteSet) addByIndex(valIndex int, vote *types.Vote) (bool, int, error) {
|
func (voteSet *VoteSet) addByIndex(valIndex int, vote *Vote) (bool, int, error) {
|
||||||
// Ensure that signer is a validator.
|
// Ensure that signer is a validator.
|
||||||
_, val := voteSet.valSet.GetByIndex(valIndex)
|
_, val := voteSet.valSet.GetByIndex(valIndex)
|
||||||
if val == nil {
|
if val == nil {
|
||||||
return false, 0, types.ErrVoteInvalidAccount
|
return false, 0, ErrVoteInvalidAccount
|
||||||
}
|
}
|
||||||
|
|
||||||
return voteSet.addVote(val, valIndex, vote)
|
return voteSet.addVote(val, valIndex, vote)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (voteSet *VoteSet) addVote(val *sm.Validator, valIndex int, vote *types.Vote) (bool, int, error) {
|
func (voteSet *VoteSet) addVote(val *Validator, valIndex int, vote *Vote) (bool, int, error) {
|
||||||
|
|
||||||
// Make sure the step matches. (or that vote is commit && round < voteSet.round)
|
// Make sure the step matches. (or that vote is commit && round < voteSet.round)
|
||||||
if (vote.Height != voteSet.height) ||
|
if (vote.Height != voteSet.height) ||
|
||||||
(vote.Round != voteSet.round) ||
|
(vote.Round != voteSet.round) ||
|
||||||
(vote.Type != voteSet.type_) {
|
(vote.Type != voteSet.type_) {
|
||||||
return false, 0, types.ErrVoteUnexpectedStep
|
return false, 0, ErrVoteUnexpectedStep
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check signature.
|
// Check signature.
|
||||||
if !val.PubKey.VerifyBytes(acm.SignBytes(config.GetString("chain_id"), vote), vote.Signature) {
|
if !val.PubKey.VerifyBytes(acm.SignBytes(config.GetString("chain_id"), vote), vote.Signature) {
|
||||||
// Bad signature.
|
// Bad signature.
|
||||||
return false, 0, types.ErrVoteInvalidSignature
|
return false, 0, ErrVoteInvalidSignature
|
||||||
}
|
}
|
||||||
|
|
||||||
// If vote already exists, return false.
|
// If vote already exists, return false.
|
||||||
@ -141,7 +139,7 @@ func (voteSet *VoteSet) addVote(val *sm.Validator, valIndex int, vote *types.Vot
|
|||||||
if bytes.Equal(existingVote.BlockHash, vote.BlockHash) {
|
if bytes.Equal(existingVote.BlockHash, vote.BlockHash) {
|
||||||
return false, valIndex, nil
|
return false, valIndex, nil
|
||||||
} else {
|
} else {
|
||||||
return false, valIndex, &types.ErrVoteConflictingSignature{
|
return false, valIndex, &ErrVoteConflictingSignature{
|
||||||
VoteA: existingVote,
|
VoteA: existingVote,
|
||||||
VoteB: vote,
|
VoteB: vote,
|
||||||
}
|
}
|
||||||
@ -176,13 +174,13 @@ func (voteSet *VoteSet) BitArray() *BitArray {
|
|||||||
return voteSet.votesBitArray.Copy()
|
return voteSet.votesBitArray.Copy()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (voteSet *VoteSet) GetByIndex(valIndex int) *types.Vote {
|
func (voteSet *VoteSet) GetByIndex(valIndex int) *Vote {
|
||||||
voteSet.mtx.Lock()
|
voteSet.mtx.Lock()
|
||||||
defer voteSet.mtx.Unlock()
|
defer voteSet.mtx.Unlock()
|
||||||
return voteSet.votes[valIndex]
|
return voteSet.votes[valIndex]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (voteSet *VoteSet) GetByAddress(address []byte) *types.Vote {
|
func (voteSet *VoteSet) GetByAddress(address []byte) *Vote {
|
||||||
voteSet.mtx.Lock()
|
voteSet.mtx.Lock()
|
||||||
defer voteSet.mtx.Unlock()
|
defer voteSet.mtx.Unlock()
|
||||||
valIndex, val := voteSet.valSet.GetByAddress(address)
|
valIndex, val := voteSet.valSet.GetByAddress(address)
|
||||||
@ -221,13 +219,13 @@ func (voteSet *VoteSet) HasTwoThirdsAny() bool {
|
|||||||
|
|
||||||
// Returns either a blockhash (or nil) that received +2/3 majority.
|
// Returns either a blockhash (or nil) that received +2/3 majority.
|
||||||
// If there exists no such majority, returns (nil, false).
|
// If there exists no such majority, returns (nil, false).
|
||||||
func (voteSet *VoteSet) TwoThirdsMajority() (hash []byte, parts types.PartSetHeader, ok bool) {
|
func (voteSet *VoteSet) TwoThirdsMajority() (hash []byte, parts PartSetHeader, ok bool) {
|
||||||
voteSet.mtx.Lock()
|
voteSet.mtx.Lock()
|
||||||
defer voteSet.mtx.Unlock()
|
defer voteSet.mtx.Unlock()
|
||||||
if voteSet.maj23Exists {
|
if voteSet.maj23Exists {
|
||||||
return voteSet.maj23Hash, voteSet.maj23Parts, true
|
return voteSet.maj23Hash, voteSet.maj23Parts, true
|
||||||
} else {
|
} else {
|
||||||
return nil, types.PartSetHeader{}, false
|
return nil, PartSetHeader{}, false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,17 +269,17 @@ func (voteSet *VoteSet) StringShort() string {
|
|||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
// Validation
|
// Validation
|
||||||
|
|
||||||
func (voteSet *VoteSet) MakeValidation() *types.Validation {
|
func (voteSet *VoteSet) MakeValidation() *Validation {
|
||||||
if voteSet.type_ != types.VoteTypePrecommit {
|
if voteSet.type_ != VoteTypePrecommit {
|
||||||
PanicSanity("Cannot MakeValidation() unless VoteSet.Type is types.VoteTypePrecommit")
|
PanicSanity("Cannot MakeValidation() unless VoteSet.Type is VoteTypePrecommit")
|
||||||
}
|
}
|
||||||
voteSet.mtx.Lock()
|
voteSet.mtx.Lock()
|
||||||
defer voteSet.mtx.Unlock()
|
defer voteSet.mtx.Unlock()
|
||||||
if len(voteSet.maj23Hash) == 0 {
|
if len(voteSet.maj23Hash) == 0 {
|
||||||
PanicSanity("Cannot MakeValidation() unless a blockhash has +2/3")
|
PanicSanity("Cannot MakeValidation() unless a blockhash has +2/3")
|
||||||
}
|
}
|
||||||
precommits := make([]*types.Vote, voteSet.valSet.Size())
|
precommits := make([]*Vote, voteSet.valSet.Size())
|
||||||
voteSet.valSet.Iterate(func(valIndex int, val *sm.Validator) bool {
|
voteSet.valSet.Iterate(func(valIndex int, val *Validator) bool {
|
||||||
vote := voteSet.votes[valIndex]
|
vote := voteSet.votes[valIndex]
|
||||||
if vote == nil {
|
if vote == nil {
|
||||||
return false
|
return false
|
||||||
@ -295,7 +293,40 @@ func (voteSet *VoteSet) MakeValidation() *types.Validation {
|
|||||||
precommits[valIndex] = vote
|
precommits[valIndex] = vote
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
return &types.Validation{
|
return &Validation{
|
||||||
Precommits: precommits,
|
Precommits: precommits,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
// For testing...
|
||||||
|
|
||||||
|
func RandValidator(randBonded bool, minBonded int64) (*ValidatorInfo, *Validator, *PrivValidator) {
|
||||||
|
privVal := GenPrivValidator()
|
||||||
|
_, tempFilePath := Tempfile("priv_validator_")
|
||||||
|
privVal.SetFile(tempFilePath)
|
||||||
|
bonded := minBonded
|
||||||
|
if randBonded {
|
||||||
|
bonded += int64(RandUint32())
|
||||||
|
}
|
||||||
|
valInfo := &ValidatorInfo{
|
||||||
|
Address: privVal.Address,
|
||||||
|
PubKey: privVal.PubKey,
|
||||||
|
UnbondTo: []*TxOutput{&TxOutput{
|
||||||
|
Amount: bonded,
|
||||||
|
Address: privVal.Address,
|
||||||
|
}},
|
||||||
|
FirstBondHeight: 0,
|
||||||
|
FirstBondAmount: bonded,
|
||||||
|
}
|
||||||
|
val := &Validator{
|
||||||
|
Address: valInfo.Address,
|
||||||
|
PubKey: valInfo.PubKey,
|
||||||
|
BondHeight: 0,
|
||||||
|
UnbondHeight: 0,
|
||||||
|
LastCommitHeight: 0,
|
||||||
|
VotingPower: valInfo.FirstBondAmount,
|
||||||
|
Accum: 0,
|
||||||
|
}
|
||||||
|
return valInfo, val, privVal
|
||||||
|
}
|
@ -1,55 +1,65 @@
|
|||||||
package consensus
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"sort"
|
||||||
|
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
. "github.com/tendermint/tendermint/common/test"
|
. "github.com/tendermint/tendermint/common/test"
|
||||||
_ "github.com/tendermint/tendermint/config/tendermint_test"
|
_ "github.com/tendermint/tendermint/config/tendermint_test"
|
||||||
sm "github.com/tendermint/tendermint/state"
|
|
||||||
"github.com/tendermint/tendermint/types"
|
|
||||||
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NOTE: see consensus/test.go for common test methods.
|
func randVoteSet(height int, round int, type_ byte, numValidators int, votingPower int64) (*VoteSet, *ValidatorSet, []*PrivValidator) {
|
||||||
|
vals := make([]*Validator, numValidators)
|
||||||
|
privValidators := make([]*PrivValidator, numValidators)
|
||||||
|
for i := 0; i < numValidators; i++ {
|
||||||
|
_, val, privValidator := RandValidator(false, votingPower)
|
||||||
|
vals[i] = val
|
||||||
|
privValidators[i] = privValidator
|
||||||
|
}
|
||||||
|
valSet := NewValidatorSet(vals)
|
||||||
|
sort.Sort(PrivValidatorsByAddress(privValidators))
|
||||||
|
return NewVoteSet(height, round, type_, valSet), valSet, privValidators
|
||||||
|
}
|
||||||
|
|
||||||
// Convenience: Return new vote with different height
|
// Convenience: Return new vote with different height
|
||||||
func withHeight(vote *types.Vote, height int) *types.Vote {
|
func withHeight(vote *Vote, height int) *Vote {
|
||||||
vote = vote.Copy()
|
vote = vote.Copy()
|
||||||
vote.Height = height
|
vote.Height = height
|
||||||
return vote
|
return vote
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convenience: Return new vote with different round
|
// Convenience: Return new vote with different round
|
||||||
func withRound(vote *types.Vote, round int) *types.Vote {
|
func withRound(vote *Vote, round int) *Vote {
|
||||||
vote = vote.Copy()
|
vote = vote.Copy()
|
||||||
vote.Round = round
|
vote.Round = round
|
||||||
return vote
|
return vote
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convenience: Return new vote with different type
|
// Convenience: Return new vote with different type
|
||||||
func withType(vote *types.Vote, type_ byte) *types.Vote {
|
func withType(vote *Vote, type_ byte) *Vote {
|
||||||
vote = vote.Copy()
|
vote = vote.Copy()
|
||||||
vote.Type = type_
|
vote.Type = type_
|
||||||
return vote
|
return vote
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convenience: Return new vote with different blockHash
|
// Convenience: Return new vote with different blockHash
|
||||||
func withBlockHash(vote *types.Vote, blockHash []byte) *types.Vote {
|
func withBlockHash(vote *Vote, blockHash []byte) *Vote {
|
||||||
vote = vote.Copy()
|
vote = vote.Copy()
|
||||||
vote.BlockHash = blockHash
|
vote.BlockHash = blockHash
|
||||||
return vote
|
return vote
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convenience: Return new vote with different blockParts
|
// Convenience: Return new vote with different blockParts
|
||||||
func withBlockParts(vote *types.Vote, blockParts types.PartSetHeader) *types.Vote {
|
func withBlockParts(vote *Vote, blockParts PartSetHeader) *Vote {
|
||||||
vote = vote.Copy()
|
vote = vote.Copy()
|
||||||
vote.BlockParts = blockParts
|
vote.BlockParts = blockParts
|
||||||
return vote
|
return vote
|
||||||
}
|
}
|
||||||
|
|
||||||
func signAddVote(privVal *sm.PrivValidator, vote *types.Vote, voteSet *VoteSet) (bool, error) {
|
func signAddVote(privVal *PrivValidator, vote *Vote, voteSet *VoteSet) (bool, error) {
|
||||||
privVal.SignVoteUnsafe(config.GetString("chain_id"), vote)
|
privVal.SignVoteUnsafe(config.GetString("chain_id"), vote)
|
||||||
added, _, err := voteSet.AddByAddress(privVal.Address, vote)
|
added, _, err := voteSet.AddByAddress(privVal.Address, vote)
|
||||||
return added, err
|
return added, err
|
||||||
@ -57,7 +67,7 @@ func signAddVote(privVal *sm.PrivValidator, vote *types.Vote, voteSet *VoteSet)
|
|||||||
|
|
||||||
func TestAddVote(t *testing.T) {
|
func TestAddVote(t *testing.T) {
|
||||||
height, round := 1, 0
|
height, round := 1, 0
|
||||||
voteSet, _, privValidators := randVoteSet(height, round, types.VoteTypePrevote, 10, 1)
|
voteSet, _, privValidators := randVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||||
val0 := privValidators[0]
|
val0 := privValidators[0]
|
||||||
|
|
||||||
// t.Logf(">> %v", voteSet)
|
// t.Logf(">> %v", voteSet)
|
||||||
@ -73,7 +83,7 @@ func TestAddVote(t *testing.T) {
|
|||||||
t.Errorf("There should be no 2/3 majority")
|
t.Errorf("There should be no 2/3 majority")
|
||||||
}
|
}
|
||||||
|
|
||||||
vote := &types.Vote{Height: height, Round: round, Type: types.VoteTypePrevote, BlockHash: nil}
|
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: nil}
|
||||||
signAddVote(val0, vote, voteSet)
|
signAddVote(val0, vote, voteSet)
|
||||||
|
|
||||||
if voteSet.GetByAddress(val0.Address) == nil {
|
if voteSet.GetByAddress(val0.Address) == nil {
|
||||||
@ -90,9 +100,9 @@ func TestAddVote(t *testing.T) {
|
|||||||
|
|
||||||
func Test2_3Majority(t *testing.T) {
|
func Test2_3Majority(t *testing.T) {
|
||||||
height, round := 1, 0
|
height, round := 1, 0
|
||||||
voteSet, _, privValidators := randVoteSet(height, round, types.VoteTypePrevote, 10, 1)
|
voteSet, _, privValidators := randVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||||
|
|
||||||
vote := &types.Vote{Height: height, Round: round, Type: types.VoteTypePrevote, BlockHash: nil}
|
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: nil}
|
||||||
|
|
||||||
// 6 out of 10 voted for nil.
|
// 6 out of 10 voted for nil.
|
||||||
for i := 0; i < 6; i++ {
|
for i := 0; i < 6; i++ {
|
||||||
@ -124,13 +134,13 @@ func Test2_3Majority(t *testing.T) {
|
|||||||
|
|
||||||
func Test2_3MajorityRedux(t *testing.T) {
|
func Test2_3MajorityRedux(t *testing.T) {
|
||||||
height, round := 1, 0
|
height, round := 1, 0
|
||||||
voteSet, _, privValidators := randVoteSet(height, round, types.VoteTypePrevote, 100, 1)
|
voteSet, _, privValidators := randVoteSet(height, round, VoteTypePrevote, 100, 1)
|
||||||
|
|
||||||
blockHash := CRandBytes(32)
|
blockHash := CRandBytes(32)
|
||||||
blockPartsTotal := 123
|
blockPartsTotal := 123
|
||||||
blockParts := types.PartSetHeader{blockPartsTotal, CRandBytes(32)}
|
blockParts := PartSetHeader{blockPartsTotal, CRandBytes(32)}
|
||||||
|
|
||||||
vote := &types.Vote{Height: height, Round: round, Type: types.VoteTypePrevote, BlockHash: blockHash, BlockParts: blockParts}
|
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: blockHash, BlockParts: blockParts}
|
||||||
|
|
||||||
// 66 out of 100 voted for nil.
|
// 66 out of 100 voted for nil.
|
||||||
for i := 0; i < 66; i++ {
|
for i := 0; i < 66; i++ {
|
||||||
@ -152,7 +162,7 @@ func Test2_3MajorityRedux(t *testing.T) {
|
|||||||
|
|
||||||
// 68th validator voted for a different BlockParts PartSetHeader
|
// 68th validator voted for a different BlockParts PartSetHeader
|
||||||
{
|
{
|
||||||
blockParts := types.PartSetHeader{blockPartsTotal, CRandBytes(32)}
|
blockParts := PartSetHeader{blockPartsTotal, CRandBytes(32)}
|
||||||
signAddVote(privValidators[67], withBlockParts(vote, blockParts), voteSet)
|
signAddVote(privValidators[67], withBlockParts(vote, blockParts), voteSet)
|
||||||
hash, header, ok = voteSet.TwoThirdsMajority()
|
hash, header, ok = voteSet.TwoThirdsMajority()
|
||||||
if hash != nil || !header.IsZero() || ok {
|
if hash != nil || !header.IsZero() || ok {
|
||||||
@ -162,7 +172,7 @@ func Test2_3MajorityRedux(t *testing.T) {
|
|||||||
|
|
||||||
// 69th validator voted for different BlockParts Total
|
// 69th validator voted for different BlockParts Total
|
||||||
{
|
{
|
||||||
blockParts := types.PartSetHeader{blockPartsTotal + 1, blockParts.Hash}
|
blockParts := PartSetHeader{blockPartsTotal + 1, blockParts.Hash}
|
||||||
signAddVote(privValidators[68], withBlockParts(vote, blockParts), voteSet)
|
signAddVote(privValidators[68], withBlockParts(vote, blockParts), voteSet)
|
||||||
hash, header, ok = voteSet.TwoThirdsMajority()
|
hash, header, ok = voteSet.TwoThirdsMajority()
|
||||||
if hash != nil || !header.IsZero() || ok {
|
if hash != nil || !header.IsZero() || ok {
|
||||||
@ -191,10 +201,10 @@ func Test2_3MajorityRedux(t *testing.T) {
|
|||||||
|
|
||||||
func TestBadVotes(t *testing.T) {
|
func TestBadVotes(t *testing.T) {
|
||||||
height, round := 1, 0
|
height, round := 1, 0
|
||||||
voteSet, _, privValidators := randVoteSet(height, round, types.VoteTypePrevote, 10, 1)
|
voteSet, _, privValidators := randVoteSet(height, round, VoteTypePrevote, 10, 1)
|
||||||
|
|
||||||
// val0 votes for nil.
|
// val0 votes for nil.
|
||||||
vote := &types.Vote{Height: height, Round: round, Type: types.VoteTypePrevote, BlockHash: nil}
|
vote := &Vote{Height: height, Round: round, Type: VoteTypePrevote, BlockHash: nil}
|
||||||
added, err := signAddVote(privValidators[0], vote, voteSet)
|
added, err := signAddVote(privValidators[0], vote, voteSet)
|
||||||
if !added || err != nil {
|
if !added || err != nil {
|
||||||
t.Errorf("Expected VoteSet.Add to succeed")
|
t.Errorf("Expected VoteSet.Add to succeed")
|
||||||
@ -219,7 +229,7 @@ func TestBadVotes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// val3 votes of another type.
|
// val3 votes of another type.
|
||||||
added, err = signAddVote(privValidators[3], withType(vote, types.VoteTypePrecommit), voteSet)
|
added, err = signAddVote(privValidators[3], withType(vote, VoteTypePrecommit), voteSet)
|
||||||
if added {
|
if added {
|
||||||
t.Errorf("Expected VoteSet.Add to fail, wrong type")
|
t.Errorf("Expected VoteSet.Add to fail, wrong type")
|
||||||
}
|
}
|
||||||
@ -227,10 +237,10 @@ func TestBadVotes(t *testing.T) {
|
|||||||
|
|
||||||
func TestMakeValidation(t *testing.T) {
|
func TestMakeValidation(t *testing.T) {
|
||||||
height, round := 1, 0
|
height, round := 1, 0
|
||||||
voteSet, _, privValidators := randVoteSet(height, round, types.VoteTypePrecommit, 10, 1)
|
voteSet, _, privValidators := randVoteSet(height, round, VoteTypePrecommit, 10, 1)
|
||||||
blockHash, blockParts := CRandBytes(32), types.PartSetHeader{123, CRandBytes(32)}
|
blockHash, blockParts := CRandBytes(32), PartSetHeader{123, CRandBytes(32)}
|
||||||
|
|
||||||
vote := &types.Vote{Height: height, Round: round, Type: types.VoteTypePrecommit,
|
vote := &Vote{Height: height, Round: round, Type: VoteTypePrecommit,
|
||||||
BlockHash: blockHash, BlockParts: blockParts}
|
BlockHash: blockHash, BlockParts: blockParts}
|
||||||
|
|
||||||
// 6 out of 10 voted for some block.
|
// 6 out of 10 voted for some block.
|
||||||
@ -244,7 +254,7 @@ func TestMakeValidation(t *testing.T) {
|
|||||||
// 7th voted for some other block.
|
// 7th voted for some other block.
|
||||||
{
|
{
|
||||||
vote := withBlockHash(vote, RandBytes(32))
|
vote := withBlockHash(vote, RandBytes(32))
|
||||||
vote = withBlockParts(vote, types.PartSetHeader{123, RandBytes(32)})
|
vote = withBlockParts(vote, PartSetHeader{123, RandBytes(32)})
|
||||||
signAddVote(privValidators[6], vote, voteSet)
|
signAddVote(privValidators[6], vote, voteSet)
|
||||||
}
|
}
|
||||||
|
|
@ -2,6 +2,7 @@ package vm
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
|
"github.com/tendermint/tendermint/types"
|
||||||
. "github.com/tendermint/tendermint/vm"
|
. "github.com/tendermint/tendermint/vm"
|
||||||
"github.com/tendermint/tendermint/vm/sha3"
|
"github.com/tendermint/tendermint/vm/sha3"
|
||||||
)
|
)
|
||||||
@ -9,7 +10,7 @@ import (
|
|||||||
type FakeAppState struct {
|
type FakeAppState struct {
|
||||||
accounts map[string]*Account
|
accounts map[string]*Account
|
||||||
storage map[string]Word256
|
storage map[string]Word256
|
||||||
logs []*Log
|
logs []types.EventDataLog
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fas *FakeAppState) GetAccount(addr Word256) *Account {
|
func (fas *FakeAppState) GetAccount(addr Word256) *Account {
|
||||||
@ -69,7 +70,7 @@ func (fas *FakeAppState) SetStorage(addr Word256, key Word256, value Word256) {
|
|||||||
fas.storage[addr.String()+key.String()] = value
|
fas.storage[addr.String()+key.String()] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fas *FakeAppState) AddLog(log *Log) {
|
func (fas *FakeAppState) AddLog(log types.EventDataLog) {
|
||||||
fas.logs = append(fas.logs, log)
|
fas.logs = append(fas.logs, log)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ func TestLog4(t *testing.T) {
|
|||||||
doneChan := make(chan struct{}, 1)
|
doneChan := make(chan struct{}, 1)
|
||||||
|
|
||||||
eventSwitch.AddListenerForEvent("test", eventId, func(event interface{}) {
|
eventSwitch.AddListenerForEvent("test", eventId, func(event interface{}) {
|
||||||
logEvent := event.(*Log)
|
logEvent := event.(types.EventDataLog)
|
||||||
// No need to test address as this event would not happen if it wasn't correct
|
// No need to test address as this event would not happen if it wasn't correct
|
||||||
if !reflect.DeepEqual(logEvent.Topics, expectedTopics) {
|
if !reflect.DeepEqual(logEvent.Topics, expectedTopics) {
|
||||||
t.Errorf("Event topics are wrong. Got: %v. Expected: %v", logEvent.Topics, expectedTopics)
|
t.Errorf("Event topics are wrong. Got: %v. Expected: %v", logEvent.Topics, expectedTopics)
|
||||||
|
@ -175,9 +175,9 @@ func runVMWaitEvents(t *testing.T, ourVm *VM, caller, callee *Account, subscribe
|
|||||||
}()
|
}()
|
||||||
msg := <-ch
|
msg := <-ch
|
||||||
switch ev := msg.(type) {
|
switch ev := msg.(type) {
|
||||||
case types.EventMsgTx:
|
case types.EventDataTx:
|
||||||
return ev.Exception
|
return ev.Exception
|
||||||
case types.EventMsgCall:
|
case types.EventDataCall:
|
||||||
return ev.Exception
|
return ev.Exception
|
||||||
case string:
|
case string:
|
||||||
return ev
|
return ev
|
||||||
|
12
vm/types.go
12
vm/types.go
@ -3,6 +3,7 @@ package vm
|
|||||||
import (
|
import (
|
||||||
. "github.com/tendermint/tendermint/common"
|
. "github.com/tendermint/tendermint/common"
|
||||||
ptypes "github.com/tendermint/tendermint/permission/types"
|
ptypes "github.com/tendermint/tendermint/permission/types"
|
||||||
|
"github.com/tendermint/tendermint/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -27,15 +28,6 @@ func (acc *Account) String() string {
|
|||||||
acc.Address, acc.Balance, acc.Code, acc.Nonce)
|
acc.Address, acc.Balance, acc.Code, acc.Nonce)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: This is serialized as an event from vm/vm.
|
|
||||||
// See: EventStringLogEvent
|
|
||||||
type Log struct {
|
|
||||||
Address Word256 `json:"address"`
|
|
||||||
Topics []Word256 `json:"topics"`
|
|
||||||
Data []byte `json:"data"`
|
|
||||||
Height int64 `json:"height"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type AppState interface {
|
type AppState interface {
|
||||||
|
|
||||||
// Accounts
|
// Accounts
|
||||||
@ -49,7 +41,7 @@ type AppState interface {
|
|||||||
SetStorage(Word256, Word256, Word256) // Setting to Zero is deleting.
|
SetStorage(Word256, Word256, Word256) // Setting to Zero is deleting.
|
||||||
|
|
||||||
// Logs
|
// Logs
|
||||||
AddLog(*Log)
|
AddLog(types.EventDataLog)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Params struct {
|
type Params struct {
|
||||||
|
4
vm/vm.go
4
vm/vm.go
@ -98,7 +98,7 @@ func HasPermission(appState AppState, acc *Account, perm ptypes.PermFlag) bool {
|
|||||||
func (vm *VM) fireCallEvent(exception *string, output *[]byte, caller, callee *Account, input []byte, value int64, gas *int64) {
|
func (vm *VM) fireCallEvent(exception *string, output *[]byte, caller, callee *Account, input []byte, value int64, gas *int64) {
|
||||||
// fire the post call event (including exception if applicable)
|
// fire the post call event (including exception if applicable)
|
||||||
if vm.evc != nil {
|
if vm.evc != nil {
|
||||||
vm.evc.FireEvent(types.EventStringAccCall(callee.Address.Postfix(20)), types.EventMsgCall{
|
vm.evc.FireEvent(types.EventStringAccCall(callee.Address.Postfix(20)), types.EventDataCall{
|
||||||
&types.CallData{caller.Address.Postfix(20), callee.Address.Postfix(20), input, value, *gas},
|
&types.CallData{caller.Address.Postfix(20), callee.Address.Postfix(20), input, value, *gas},
|
||||||
vm.origin.Postfix(20),
|
vm.origin.Postfix(20),
|
||||||
vm.txid,
|
vm.txid,
|
||||||
@ -694,7 +694,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
|
|||||||
if !ok {
|
if !ok {
|
||||||
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
return nil, firstErr(err, ErrMemoryOutOfBounds)
|
||||||
}
|
}
|
||||||
log := &Log{
|
log := types.EventDataLog{
|
||||||
callee.Address,
|
callee.Address,
|
||||||
topics,
|
topics,
|
||||||
data,
|
data,
|
||||||
|
@ -585,6 +585,7 @@ func readByteJSON(o interface{}) (typeByte byte, rest interface{}, err error) {
|
|||||||
|
|
||||||
// Contract: Caller must ensure that rt is supported
|
// Contract: Caller must ensure that rt is supported
|
||||||
// (e.g. is recursively composed of supported native types, and structs and slices.)
|
// (e.g. is recursively composed of supported native types, and structs and slices.)
|
||||||
|
// rv and rt refer to the object we're unmarhsaling into, whereas o is the result of naiive json unmarshal (map[string]interface{})
|
||||||
func readReflectJSON(rv reflect.Value, rt reflect.Type, o interface{}, err *error) {
|
func readReflectJSON(rv reflect.Value, rt reflect.Type, o interface{}, err *error) {
|
||||||
|
|
||||||
// Get typeInfo
|
// Get typeInfo
|
||||||
|
@ -71,6 +71,7 @@ func ReadJSONPtr(o interface{}, bytes []byte, err *error) interface{} {
|
|||||||
return ReadJSONObjectPtr(o, object, err)
|
return ReadJSONObjectPtr(o, object, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// o is the ultimate destination, object is the result of json unmarshal
|
||||||
func ReadJSONObject(o interface{}, object interface{}, err *error) interface{} {
|
func ReadJSONObject(o interface{}, object interface{}, err *error) interface{} {
|
||||||
rv, rt := reflect.ValueOf(o), reflect.TypeOf(o)
|
rv, rt := reflect.ValueOf(o), reflect.TypeOf(o)
|
||||||
if rv.Kind() == reflect.Ptr {
|
if rv.Kind() == reflect.Ptr {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user