RPCResponse.Result && EventData are registered interfaces; -skip_upnp option

This commit is contained in:
Jae Kwon 2015-08-10 20:38:45 -07:00
parent 65d40a2d08
commit 1b9fd811a1
60 changed files with 1468 additions and 1398 deletions

View File

@ -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))

View File

@ -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

View 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)

View File

@ -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()
}

View File

@ -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")

View File

@ -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")

View File

@ -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 {

View File

@ -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 {

View File

@ -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)

View File

@ -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
}

View File

@ -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

View File

@ -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)
} }

View File

@ -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 {

View File

@ -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())

View File

@ -1,4 +1,4 @@
package consensus package p2p
import ( import (
cfg "github.com/tendermint/tendermint/config" cfg "github.com/tendermint/tendermint/config"

View File

@ -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)

View File

@ -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()

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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
View 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")

View File

@ -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
} }
} }
} }

View File

@ -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
} }

View File

@ -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")

View File

@ -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))
} }

View File

@ -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
} }
//-------------------------------------------------------------------------------- //--------------------------------------------------------------------------------

View File

@ -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")
} }
} }

View File

@ -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
} }

View File

@ -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"`
}

View File

@ -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)
}

View File

@ -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,
}
}

View File

@ -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"

View File

@ -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)

View File

@ -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,
}
} }

View File

@ -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
}

View File

@ -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
View 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
}

View File

@ -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"`
} }

View File

@ -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
}

View File

@ -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,

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -1,4 +1,4 @@
package state package types
import ( import (
"github.com/tendermint/tendermint/account" "github.com/tendermint/tendermint/account"

View File

@ -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
}

View File

@ -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)
} }

View File

@ -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)
} }

View File

@ -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)

View File

@ -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

View File

@ -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 {

View File

@ -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,

View File

@ -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

View File

@ -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 {