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/rpc/client"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
cclient "github.com/tendermint/tendermint/rpc/core_client"
"github.com/tendermint/tendermint/types"
)
@ -75,7 +76,7 @@ func main() {
sendTx := makeRandomTransaction(10, rootAccount.Sequence+1, root, 2, accounts)
fmt.Println(sendTx)
wsClient := rpcclient.NewWSClient("ws://" + remote + "/websocket")
wsClient := cclient.NewWSClient("ws://" + remote + "/websocket")
_, err = wsClient.Start()
if err != nil {
Exit(Fmt("Failed to establish websocket connection: %v", err))

View File

@ -3,13 +3,13 @@ package main
import (
"fmt"
"github.com/tendermint/tendermint/types"
"github.com/tendermint/tendermint/wire"
sm "github.com/tendermint/tendermint/state"
)
func gen_validator() {
privValidator := sm.GenPrivValidator()
privValidator := types.GenPrivValidator()
privValidatorJSONBytes := wire.JSONBytes(privValidator)
fmt.Printf(`Generated a new validator!
Paste the following JSON into your %v file

View File

@ -3,24 +3,24 @@ package main
import (
"os"
sm "github.com/tendermint/tendermint/state"
"github.com/tendermint/tendermint/types"
)
// NOTE: this is totally unsafe.
// it's only suitable for testnets.
func reset_priv_validator() {
// Get PrivValidator
var privValidator *sm.PrivValidator
var privValidator *types.PrivValidator
privValidatorFile := config.GetString("priv_validator_file")
if _, err := os.Stat(privValidatorFile); err == nil {
privValidator = sm.LoadPrivValidator(privValidatorFile)
privValidator = types.LoadPrivValidator(privValidatorFile)
privValidator.LastHeight = 0
privValidator.LastRound = 0
privValidator.LastStep = 0
privValidator.Save()
log.Notice("Reset PrivValidator", "file", privValidatorFile)
} else {
privValidator = sm.GenPrivValidator()
privValidator = types.GenPrivValidator()
privValidator.SetFile(privValidatorFile)
privValidator.Save()
log.Notice("Generated PrivValidator", "file", privValidatorFile)

View File

@ -198,3 +198,11 @@ func (af *AutoFile) openFile() error {
af.file = file
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("seeds", "goldenalchemist.chaintest.net:46656")
mapConfig.SetDefault("fast_sync", true)
mapConfig.SetDefault("skip_upnp", false)
mapConfig.SetDefault("addrbook_file", rootDir+"/addrbook.json")
mapConfig.SetDefault("priv_validator_file", rootDir+"/priv_validator.json")
mapConfig.SetDefault("db_backend", "leveldb")

View File

@ -68,6 +68,7 @@ func GetConfig(rootDir string) cfg.Config {
mapConfig.SetDefault("moniker", "anonymous")
mapConfig.SetDefault("node_laddr", "0.0.0.0:36656")
mapConfig.SetDefault("fast_sync", false)
mapConfig.SetDefault("skip_upnp", true)
mapConfig.SetDefault("addrbook_file", rootDir+"/addrbook.json")
mapConfig.SetDefault("priv_validator_file", rootDir+"/priv_validator.json")
mapConfig.SetDefault("db_backend", "memdb")

View File

@ -5,13 +5,12 @@ import (
"sync"
. "github.com/tendermint/tendermint/common"
sm "github.com/tendermint/tendermint/state"
"github.com/tendermint/tendermint/types"
)
type RoundVoteSet struct {
Prevotes *VoteSet
Precommits *VoteSet
Prevotes *types.VoteSet
Precommits *types.VoteSet
}
/*
@ -28,7 +27,7 @@ peer to prevent abuse.
*/
type HeightVoteSet struct {
height int
valSet *sm.ValidatorSet
valSet *types.ValidatorSet
mtx sync.Mutex
round int // max tracked round
@ -36,7 +35,7 @@ type HeightVoteSet struct {
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{
height: height,
valSet: valSet,
@ -79,8 +78,8 @@ func (hvs *HeightVoteSet) addRound(round int) {
PanicSanity("addRound() for an existing round")
}
log.Info("addRound(round)", "round", round)
prevotes := NewVoteSet(hvs.height, round, types.VoteTypePrevote, hvs.valSet)
precommits := NewVoteSet(hvs.height, round, types.VoteTypePrecommit, hvs.valSet)
prevotes := types.NewVoteSet(hvs.height, round, types.VoteTypePrevote, hvs.valSet)
precommits := types.NewVoteSet(hvs.height, round, types.VoteTypePrecommit, hvs.valSet)
hvs.roundVoteSets[round] = RoundVoteSet{
Prevotes: prevotes,
Precommits: precommits,
@ -109,13 +108,13 @@ func (hvs *HeightVoteSet) AddByAddress(address []byte, vote *types.Vote, peerKey
return
}
func (hvs *HeightVoteSet) Prevotes(round int) *VoteSet {
func (hvs *HeightVoteSet) Prevotes(round int) *types.VoteSet {
hvs.mtx.Lock()
defer hvs.mtx.Unlock()
return hvs.getVoteSet(round, types.VoteTypePrevote)
}
func (hvs *HeightVoteSet) Precommits(round int) *VoteSet {
func (hvs *HeightVoteSet) Precommits(round int) *types.VoteSet {
hvs.mtx.Lock()
defer hvs.mtx.Unlock()
return hvs.getVoteSet(round, types.VoteTypePrecommit)
@ -134,7 +133,7 @@ func (hvs *HeightVoteSet) POLRound() int {
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_)
rvs, ok := hvs.roundVoteSets[round]
if !ok {

View File

@ -10,7 +10,6 @@ import (
bc "github.com/tendermint/tendermint/blockchain"
. "github.com/tendermint/tendermint/common"
. "github.com/tendermint/tendermint/consensus/types"
"github.com/tendermint/tendermint/events"
"github.com/tendermint/tendermint/p2p"
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) {
case *VoteMessage:
vote := msg.Vote
var validators *sm.ValidatorSet
var validators *types.ValidatorSet
if rs.Height == vote.Height {
validators = rs.Validators
} 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.
func (conR *ConsensusReactor) SetPrivValidator(priv *sm.PrivValidator) {
func (conR *ConsensusReactor) SetPrivValidator(priv *types.PrivValidator) {
conR.conS.SetPrivValidator(priv)
}
@ -598,7 +597,7 @@ func (ps *PeerState) GetRoundState() *PeerRoundState {
return &prs
}
func (ps *PeerState) SetHasProposal(proposal *Proposal) {
func (ps *PeerState) SetHasProposal(proposal *types.Proposal) {
ps.mtx.Lock()
defer ps.mtx.Unlock()
@ -964,7 +963,7 @@ func (m *CommitStepMessage) String() string {
//-------------------------------------
type ProposalMessage struct {
Proposal *Proposal
Proposal *types.Proposal
}
func (m *ProposalMessage) String() string {

View File

@ -160,7 +160,6 @@ import (
acm "github.com/tendermint/tendermint/account"
bc "github.com/tendermint/tendermint/blockchain"
. "github.com/tendermint/tendermint/common"
. "github.com/tendermint/tendermint/consensus/types"
"github.com/tendermint/tendermint/events"
mempl "github.com/tendermint/tendermint/mempool"
sm "github.com/tendermint/tendermint/state"
@ -231,16 +230,16 @@ type RoundState struct {
Step RoundStepType
StartTime time.Time
CommitTime time.Time // Subjective time when +2/3 precommits for Block at Round were found
Validators *sm.ValidatorSet
Proposal *Proposal
Validators *types.ValidatorSet
Proposal *types.Proposal
ProposalBlock *types.Block
ProposalBlockParts *types.PartSet
LockedRound int
LockedBlock *types.Block
LockedBlockParts *types.PartSet
Votes *HeightVoteSet
LastCommit *VoteSet // Last precommits at Height-1
LastValidators *sm.ValidatorSet
LastCommit *types.VoteSet // Last precommits at Height-1
LastValidators *types.ValidatorSet
}
func (rs *RoundState) String() string {
@ -288,7 +287,7 @@ type ConsensusState struct {
blockStore *bc.BlockStore
mempoolReactor *mempl.MempoolReactor
privValidator *sm.PrivValidator
privValidator *types.PrivValidator
newStepCh chan *RoundState
mtx sync.Mutex
@ -322,7 +321,7 @@ func (cs *ConsensusState) reconstructLastCommit(state *sm.State) {
if state.LastBlockHeight == 0 {
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)
for idx, precommit := range seenValidation.Precommits {
if precommit == nil {
@ -408,7 +407,7 @@ func (cs *ConsensusState) updateToState(state *sm.State, contiguous bool) {
// Reset fields based on state.
validators := state.BondedValidators
height := state.LastBlockHeight + 1 // next desired block height
lastPrecommits := (*VoteSet)(nil)
lastPrecommits := (*types.VoteSet)(nil)
if contiguous && cs.Votes != nil {
if !cs.Votes.Precommits(cs.Round).HasTwoThirdsMajority() {
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()
defer cs.mtx.Unlock()
cs.privValidator = priv
@ -580,7 +579,7 @@ func (cs *ConsensusState) decideProposal(height int, round int) {
}
// 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)
if err == nil {
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()
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
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.
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
go func(block *types.Block) {
cs.evsw.FireEvent(types.EventStringNewBlock(), block)
cs.evsw.FireEvent(types.EventStringNewBlock(), types.EventDataNewBlock{block})
cs.evc.Flush()
}(block)

View File

@ -1,15 +1,14 @@
package consensus
import (
"sort"
bc "github.com/tendermint/tendermint/blockchain"
dbm "github.com/tendermint/tendermint/db"
mempl "github.com/tendermint/tendermint/mempool"
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)
blockStore := bc.NewBlockStore(dbm.NewMemDB())
mempool := mempl.NewMempool(state)
@ -17,16 +16,3 @@ func randConsensusState() (*ConsensusState, []*sm.PrivValidator) {
cs := NewConsensusState(state, blockStore, mempoolReactor)
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"
. "github.com/tendermint/tendermint/common"
"github.com/tendermint/tendermint/rpc/client"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
core "github.com/tendermint/tendermint/rpc/core_client"
"github.com/tendermint/tendermint/rpc/types"
cclient "github.com/tendermint/tendermint/rpc/core_client"
"github.com/tendermint/tendermint/types"
"github.com/tendermint/tendermint/wire"
)
const (
@ -37,7 +34,7 @@ type Node struct {
ChainID string
BlockHeight int
BlockHistory map[int]time.Time // when we saw each block
NetInfo *ctypes.ResponseNetInfo
NetInfo *ctypes.ResultNetInfo
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
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.ChainID = status.NodeInfo.ChainID
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
type NodeClient struct {
rpc core.Client
ws *rpcclient.WSClient
rpc cclient.Client
ws *cclient.WSClient
}
// Create a new client for the node at the given addr
func NewNodeClient(addr string) *NodeClient {
return &NodeClient{
rpc: core.NewClient("http://"+addr, "JSONRPC"),
ws: rpcclient.NewWSClient("ws://" + addr + "/events"),
rpc: cclient.NewClient("http://"+addr, "JSONRPC"),
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 {
var block *types.Block
var err error
wire.ReadJSONObject(block, eventMsg.Data, &err)
func (c *Crawler) consumeMessage(eventMsg ctypes.ResultEvent, node *Node) error {
block := eventMsg.Data.(*types.Block)
node.LastSeen = time.Now()
node.BlockHeight = block.Height
node.BlockHistory[block.Height] = node.LastSeen

View File

@ -1,5 +1,9 @@
package events
import (
"github.com/tendermint/tendermint/types"
)
const (
eventsBufferSize = 1000
)
@ -22,20 +26,20 @@ func NewEventCache(evsw Fireable) *EventCache {
// a cached event
type eventInfo struct {
event string
msg interface{}
data types.EventData
}
// 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
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.
// Clears cached events
func (evc *EventCache) Flush() {
for _, ei := range evc.events {
evc.evsw.FireEvent(ei.event, ei.msg)
evc.evsw.FireEvent(ei.event, ei.data)
}
evc.events = make([]eventInfo, eventsBufferSize)
}

View File

@ -21,6 +21,7 @@ import (
"github.com/tendermint/tendermint/rpc/core"
"github.com/tendermint/tendermint/rpc/server"
sm "github.com/tendermint/tendermint/state"
stypes "github.com/tendermint/tendermint/state/types"
"github.com/tendermint/tendermint/types"
"github.com/tendermint/tendermint/wire"
)
@ -37,8 +38,8 @@ type Node struct {
mempoolReactor *mempl.MempoolReactor
consensusState *consensus.ConsensusState
consensusReactor *consensus.ConsensusReactor
privValidator *sm.PrivValidator
genDoc *sm.GenesisDoc
privValidator *types.PrivValidator
genDoc *stypes.GenesisDoc
privKey acm.PrivKeyEd25519
}
@ -50,19 +51,19 @@ func NewNode() *Node {
// Get State
stateDB := dbm.GetDB("state")
state := sm.LoadState(stateDB)
var genDoc *sm.GenesisDoc
var genDoc *stypes.GenesisDoc
if state == nil {
genDoc, state = sm.MakeGenesisStateFromFile(stateDB, config.GetString("genesis_file"))
state.Save()
// write the gendoc to db
buf, n, err := new(bytes.Buffer), new(int64), new(error)
wire.WriteJSON(genDoc, buf, n, err)
stateDB.Set(sm.GenDocKey, buf.Bytes())
stateDB.Set(stypes.GenDocKey, buf.Bytes())
if *err != nil {
Exit(Fmt("Unable to write gendoc to db: %v", err))
}
} else {
genDocBytes := stateDB.Get(sm.GenDocKey)
genDocBytes := stateDB.Get(stypes.GenDocKey)
err := new(error)
wire.ReadJSONPtr(&genDoc, genDocBytes, err)
if *err != nil {
@ -73,14 +74,14 @@ func NewNode() *Node {
config.Set("chain_id", state.ChainID)
// Get PrivValidator
var privValidator *sm.PrivValidator
var privValidator *types.PrivValidator
privValidatorFile := config.GetString("priv_validator_file")
if _, err := os.Stat(privValidatorFile); err == nil {
privValidator = sm.LoadPrivValidator(privValidatorFile)
privValidator = types.LoadPrivValidator(privValidatorFile)
log.Notice("Loaded PrivValidator",
"file", privValidatorFile, "privValidator", privValidator)
} else {
privValidator = sm.GenPrivValidator()
privValidator = types.GenPrivValidator()
privValidator.SetFile(privValidatorFile)
privValidator.Save()
log.Notice("Generated PrivValidator", "file", privValidatorFile)
@ -281,7 +282,7 @@ func makeNodeInfo(sw *p2p.Switch, privKey acm.PrivKeyEd25519) *types.NodeInfo {
func RunNode() {
// Create & start node
n := NewNode()
l := p2p.NewDefaultListener("tcp", config.GetString("node_laddr"), false)
l := p2p.NewDefaultListener("tcp", config.GetString("node_laddr"))
n.AddListener(l)
err := n.Start()
if err != nil {

View File

@ -11,7 +11,7 @@ import (
func TestNodeStartStop(t *testing.T) {
// Create & start node
n := NewNode()
l := p2p.NewDefaultListener("tcp", config.GetString("node_laddr"), false)
l := p2p.NewDefaultListener("tcp", config.GetString("node_laddr"))
n.AddListener(l)
n.Start()
log.Notice("Started node", "nodeInfo", n.sw.NodeInfo())

View File

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

View File

@ -46,7 +46,7 @@ func splitHostPort(addr string) (host string, port int) {
return host, port
}
func NewDefaultListener(protocol string, lAddr string, requireUPNPHairpin bool) Listener {
func NewDefaultListener(protocol string, lAddr string) Listener {
// Local listen IP & port
lAddrIP, lAddrPort := splitHostPort(lAddr)
@ -73,22 +73,12 @@ func NewDefaultListener(protocol string, lAddr string, requireUPNPHairpin bool)
// Determine external address...
var extAddr *NetAddress
// If the lAddrIP is INADDR_ANY, try UPnP
if lAddrIP == "" || lAddrIP == "0.0.0.0" {
if requireUPNPHairpin {
upnpCapabilities, err := upnp.Probe()
if err != nil {
log.Warn("Failed to probe UPNP", "error", err)
goto SKIP_UPNP
}
if !upnpCapabilities.Hairpin {
goto SKIP_UPNP
}
if !config.GetBool("skip_upnp") {
// If the lAddrIP is INADDR_ANY, try UPnP
if lAddrIP == "" || lAddrIP == "0.0.0.0" {
extAddr = getUPNPExternalAddress(lAddrPort, listenerPort)
}
extAddr = getUPNPExternalAddress(lAddrPort, listenerPort)
}
SKIP_UPNP:
// Otherwise just use the local address...
if extAddr == nil {
extAddr = getNaiveExternalAddress(listenerPort)

View File

@ -7,9 +7,10 @@ import (
"time"
acm "github.com/tendermint/tendermint/account"
"github.com/tendermint/tendermint/wire"
. "github.com/tendermint/tendermint/common"
_ "github.com/tendermint/tendermint/config/tendermint_test"
"github.com/tendermint/tendermint/types"
"github.com/tendermint/tendermint/wire"
)
type PeerMessage struct {
@ -97,7 +98,7 @@ func makeSwitchPair(t testing.TB, initSwitch func(*Switch) *Switch) (*Switch, *S
s2.Start()
// Create a listener for s1
l := NewDefaultListener("tcp", ":8001", true)
l := NewDefaultListener("tcp", ":8001")
// Dial the listener & add the connection to s2.
lAddr := l.ExternalAddress()

View File

@ -7,21 +7,21 @@ import (
ctypes "github.com/tendermint/tendermint/rpc/core/types"
)
func GenPrivAccount() (*acm.PrivAccount, error) {
return acm.GenPrivAccount(), nil
func GenPrivAccount() (*ctypes.ResultGenPrivAccount, error) {
return &ctypes.ResultGenPrivAccount{acm.GenPrivAccount()}, 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()
account := cache.GetAccount(address)
if account == 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()
account := state.GetAccount(address)
if account == nil {
@ -32,12 +32,12 @@ func GetStorage(address, key []byte) (*ctypes.ResponseGetStorage, error) {
_, value := storageTree.Get(LeftPadWord256(key).Bytes())
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 accounts []*acm.Account
state := consensusState.GetState()
@ -46,10 +46,10 @@ func ListAccounts() (*ctypes.ResponseListAccounts, error) {
accounts = append(accounts, value.(*acm.Account))
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()
account := state.GetAccount(address)
if account == nil {
@ -63,5 +63,5 @@ func DumpStorage(address []byte) (*ctypes.ResponseDumpStorage, error) {
key.([]byte), value.([]byte)})
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 {
maxHeight = blockStore.Height()
} else {
@ -26,12 +26,12 @@ func BlockchainInfo(minHeight, maxHeight int) (*ctypes.ResponseBlockchainInfo, e
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 {
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)
block := blockStore.LoadBlock(height)
return &ctypes.ResponseGetBlock{blockMeta, block}, nil
return &ctypes.ResultGetBlock{blockMeta, block}, nil
}

View File

@ -1,32 +1,32 @@
package core
import (
"github.com/tendermint/tendermint/wire"
cm "github.com/tendermint/tendermint/consensus"
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 bondedValidators []*sm.Validator
var unbondingValidators []*sm.Validator
var bondedValidators []*types.Validator
var unbondingValidators []*types.Validator
state := consensusState.GetState()
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)
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)
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()
peerRoundStates := []string{}
for _, peer := range p2pSwitch.Peers().List() {
@ -36,5 +36,5 @@ func DumpConsensusState() (*ctypes.ResponseDumpConsensusState, error) {
peerRoundStateStr := peer.Key + ":" + string(wire.JSONBytes(peerRoundState))
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
func BroadcastTx(tx types.Tx) (*ctypes.Receipt, error) {
func BroadcastTx(tx types.Tx) (*ctypes.ResultBroadcastTx, error) {
err := mempoolReactor.BroadcastTx(tx)
if err != nil {
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)
}
}
return &ctypes.Receipt{txHash, createsContract, contractAddr}, nil
return &ctypes.ResultBroadcastTx{ctypes.Receipt{txHash, createsContract, contractAddr}}, nil
}
func ListUnconfirmedTxs() ([]types.Tx, error) {
return mempoolReactor.Mempool.GetProposalTxs(), nil
func ListUnconfirmedTxs() (*ctypes.ResultListUnconfirmedTxs, error) {
return &ctypes.ResultListUnconfirmedTxs{mempoolReactor.Mempool.GetProposalTxs()}, nil
}

View File

@ -7,16 +7,16 @@ import (
"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
entry := st.GetNameRegEntry(name)
if entry == nil {
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 names []*types.NameRegEntry
state := consensusState.GetState()
@ -25,5 +25,5 @@ func ListNames() (*ctypes.ResponseListNames, error) {
names = append(names, value.(*types.NameRegEntry))
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
var genesisState *sm.State
func Status() (*ctypes.ResponseStatus, error) {
func Status() (*ctypes.ResultStatus, error) {
db := dbm.NewMemDB()
if genesisState == nil {
genesisState = sm.MakeGenesisState(db, genDoc)
@ -30,7 +30,7 @@ func Status() (*ctypes.ResponseStatus, error) {
latestBlockTime = latestBlockMeta.Header.Time.UnixNano()
}
return &ctypes.ResponseStatus{
return &ctypes.ResultStatus{
NodeInfo: p2pSwitch.NodeInfo(),
GenesisHash: genesisHash,
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()
listeners := []string{}
for _, listener := range p2pSwitch.Listeners() {
@ -54,7 +54,7 @@ func NetInfo() (*ctypes.ResponseNetInfo, error) {
IsOutbound: peer.IsOutbound(),
})
}
return &ctypes.ResponseNetInfo{
return &ctypes.ResultNetInfo{
Listening: listening,
Listeners: listeners,
Peers: peers,
@ -63,6 +63,6 @@ func NetInfo() (*ctypes.ResponseNetInfo, error) {
//-----------------------------------------------------------------------------
func Genesis() (*sm.GenesisDoc, error) {
return genDoc, nil
func Genesis() (*ctypes.ResultGenesis, error) {
return &ctypes.ResultGenesis{genDoc}, nil
}

View File

@ -5,7 +5,8 @@ import (
"github.com/tendermint/tendermint/consensus"
mempl "github.com/tendermint/tendermint/mempool"
"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
@ -13,8 +14,8 @@ var consensusState *consensus.ConsensusState
var consensusReactor *consensus.ConsensusReactor
var mempoolReactor *mempl.MempoolReactor
var p2pSwitch *p2p.Switch
var privValidator *state.PrivValidator
var genDoc *state.GenesisDoc // cache the genesis structure
var privValidator *types.PrivValidator
var genDoc *stypes.GenesisDoc // cache the genesis structure
func SetBlockStore(bs *bc.BlockStore) {
blockStore = bs
@ -36,10 +37,10 @@ func SetSwitch(sw *p2p.Switch) {
p2pSwitch = sw
}
func SetPrivValidator(pv *state.PrivValidator) {
func SetPrivValidator(pv *types.PrivValidator) {
privValidator = pv
}
func SetGenDoc(doc *state.GenesisDoc) {
func SetGenDoc(doc *stypes.GenesisDoc) {
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
// 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
cache := state.NewBlockCache(st)
outAcc := cache.GetAccount(toAddress)
@ -47,12 +47,12 @@ func Call(fromAddress, toAddress, data []byte) (*ctypes.ResponseCall, error) {
if err != nil {
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
// 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
cache := mempoolReactor.Mempool.GetCache()
@ -72,12 +72,12 @@ func CallCode(fromAddress, code, data []byte) (*ctypes.ResponseCall, error) {
if err != nil {
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?
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.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 (
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/wire"
)
type ResponseGetStorage struct {
type ResultGetStorage struct {
Key []byte `json:"key"`
Value []byte `json:"value"`
}
type ResponseCall struct {
type ResultCall struct {
Return []byte `json:"return"`
GasUsed int64 `json:"gas_used"`
// TODO ...
}
type ResponseListAccounts struct {
type ResultListAccounts struct {
BlockHeight int `json:"block_height"`
Accounts []*acm.Account `json:"accounts"`
}
type ResultDumpStorage struct {
StorageRoot []byte `json:"storage_root"`
StorageItems []StorageItem `json:"storage_items"`
}
type StorageItem struct {
Key []byte `json:"key"`
Value []byte `json:"value"`
}
type ResponseDumpStorage struct {
StorageRoot []byte `json:"storage_root"`
StorageItems []StorageItem `json:"storage_items"`
}
type ResponseBlockchainInfo struct {
type ResultBlockchainInfo struct {
LastHeight int `json:"last_height"`
BlockMetas []*types.BlockMeta `json:"block_metas"`
}
type ResponseGetBlock struct {
type ResultGetBlock struct {
BlockMeta *types.BlockMeta `json:"block_meta"`
Block *types.Block `json:"block"`
}
type Receipt struct {
TxHash []byte `json:"tx_hash"`
CreatesContract uint8 `json:"creates_contract"`
ContractAddr []byte `json:"contract_addr"`
}
type ResponseStatus struct {
type ResultStatus struct {
NodeInfo *types.NodeInfo `json:"node_info"`
GenesisHash []byte `json:"genesis_hash"`
PubKey acm.PubKey `json:"pub_key"`
@ -57,7 +52,7 @@ type ResponseStatus struct {
LatestBlockTime int64 `json:"latest_block_time"` // nano
}
type ResponseNetInfo struct {
type ResultNetInfo struct {
Listening bool `json:"listening"`
Listeners []string `json:"listeners"`
Peers []Peer `json:"peers"`
@ -68,26 +63,115 @@ type Peer struct {
IsOutbound bool `json:"is_outbound"`
}
type ResponseListValidators struct {
BlockHeight int `json:"block_height"`
BondedValidators []*sm.Validator `json:"bonded_validators"`
UnbondingValidators []*sm.Validator `json:"unbonding_validators"`
type ResultListValidators struct {
BlockHeight int `json:"block_height"`
BondedValidators []*types.Validator `json:"bonded_validators"`
UnbondingValidators []*types.Validator `json:"unbonding_validators"`
}
type ResponseDumpConsensusState struct {
type ResultDumpConsensusState struct {
RoundState string `json:"round_state"`
PeerRoundStates []string `json:"peer_round_states"`
}
type ResponseListNames struct {
type ResultListNames struct {
BlockHeight int `json:"block_height"`
Names []*types.NameRegEntry `json:"names"`
}
//----------------------------------------
// event responses
type ResponseEvent struct {
Event string `json:"event"`
Data interface{} `json:"data"`
type ResultGenPrivAccount struct {
PrivAccount *acm.PrivAccount `json:"priv_account"`
}
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 (
"encoding/json"
@ -8,27 +8,28 @@ import (
"github.com/tendermint/tendermint/Godeps/_workspace/src/github.com/gorilla/websocket"
. "github.com/tendermint/tendermint/common"
_ "github.com/tendermint/tendermint/config/tendermint_test"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
"github.com/tendermint/tendermint/rpc/types"
)
const wsEventsChannelCapacity = 10
const wsResponsesChannelCapacity = 10
const wsResultsChannelCapacity = 10
type WSClient struct {
QuitService
Address string
*websocket.Conn
EventsCh chan rpctypes.RPCEventResult
ResponsesCh chan rpctypes.RPCResponse
EventsCh chan ctypes.ResultEvent
ResultsCh chan ctypes.Result
}
// create a new connection
func NewWSClient(addr string) *WSClient {
wsClient := &WSClient{
Address: addr,
Conn: nil,
EventsCh: make(chan rpctypes.RPCEventResult, wsEventsChannelCapacity),
ResponsesCh: make(chan rpctypes.RPCResponse, wsResponsesChannelCapacity),
Address: addr,
Conn: nil,
EventsCh: make(chan ctypes.ResultEvent, wsEventsChannelCapacity),
ResultsCh: make(chan ctypes.Result, wsResultsChannelCapacity),
}
wsClient.QuitService = *NewQuitService(log, "WSClient", wsClient)
return wsClient
@ -68,19 +69,16 @@ func (wsc *WSClient) receiveEventsRoutine() {
wsc.Stop()
break
} else {
var response rpctypes.RPCResponse
var response ctypes.Response
if err := json.Unmarshal(data, &response); err != nil {
log.Info(Fmt("WSClient failed to parse message: %v", err))
wsc.Stop()
break
}
if strings.HasSuffix(response.Id, "#event") {
result := response.Result.(map[string]interface{})
event := result["event"].(string)
data := result["data"]
wsc.EventsCh <- rpctypes.RPCEventResult{event, data}
wsc.EventsCh <- response.Result.(ctypes.ResultEvent)
} 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/common"
"github.com/tendermint/tendermint/events"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
. "github.com/tendermint/tendermint/rpc/types"
"github.com/tendermint/tendermint/wire"
)
@ -338,7 +339,7 @@ func (wsc *WSConnection) readRoutine() {
log.Notice("Subscribe to event", "id", wsc.id, "event", event)
wsc.evsw.AddListenerForEvent(wsc.id, event, func(msg interface{}) {
// 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
}

View File

@ -11,9 +11,9 @@ import (
"time"
"github.com/tendermint/tendermint/alert"
"github.com/tendermint/tendermint/wire"
. "github.com/tendermint/tendermint/common"
. "github.com/tendermint/tendermint/rpc/types"
"github.com/tendermint/tendermint/wire"
)
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) {
buf, n, err := new(bytes.Buffer), new(int64), new(error)
wire.WriteJSON(res, buf, n, err)
if *err != nil {
log.Warn("Failed to write RPC response", "error", err)
buf, n, err := new(bytes.Buffer), int64(0), error(nil)
wire.WriteJSON(res, buf, &n, &err)
if err != nil {
log.Error("Failed to write RPC response", "error", err, "res", res)
}
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)
receipt := broadcastTx(t, wsTyp, tx)
contractAddr = receipt.ContractAddr
}, unmarshalValidateCall(amt, returnCode))
}, unmarshalValidateTx(amt, returnCode))
// susbscribe to the new contract
amt = int64(10001)
@ -135,7 +135,7 @@ func TestWSCallWait(t *testing.T) {
tx := makeDefaultCallTx(t, wsTyp, contractAddr, data, amt, gasLim, fee)
receipt := broadcastTx(t, wsTyp, tx)
contractAddr = receipt.ContractAddr
}, unmarshalValidateCall(amt, returnVal))
}, unmarshalValidateTx(amt, returnVal))
}
// 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() {
tx := makeDefaultCallTx(t, wsTyp, contractAddr, data, amt, gasLim, fee)
broadcastTx(t, wsTyp, tx)
}, unmarshalValidateCall(amt, returnVal))
}, unmarshalValidateTx(amt, returnVal))
}
// 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)
broadcastTx(t, wsTyp, 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"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
cclient "github.com/tendermint/tendermint/rpc/core_client"
"github.com/tendermint/tendermint/state"
"github.com/tendermint/tendermint/types"
)
@ -51,7 +50,7 @@ func makeUsers(n int) []*acm.PrivAccount {
func newNode(ready chan struct{}) {
// Create & start node
node = nm.NewNode()
l := p2p.NewDefaultListener("tcp", config.GetString("node_laddr"), false)
l := p2p.NewDefaultListener("tcp", config.GetString("node_laddr"))
node.AddListener(l)
node.Start()
@ -69,7 +68,7 @@ func init() {
chainID = config.GetString("chain_id")
// Save new priv_validator file.
priv := &state.PrivValidator{
priv := &types.PrivValidator{
Address: user[0].Address,
PubKey: acm.PubKeyEd25519(user[0].PubKey.(acm.PubKeyEd25519)),
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 {
t.Fatal(err)
}
if ac == nil {
if ac.Account == nil {
return 0
}
return ac.Sequence
return ac.Account.Sequence
}
// get the account
@ -139,7 +138,7 @@ func getAccount(t *testing.T, typ string, addr []byte) *acm.Account {
if err != nil {
t.Fatal(err)
}
return ac
return ac.Account
}
// sign transaction
@ -149,22 +148,22 @@ func signTx(t *testing.T, typ string, tx types.Tx, privAcc *acm.PrivAccount) typ
if err != nil {
t.Fatal(err)
}
return signedTx
return signedTx.Tx
}
// 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]
rec, err := client.BroadcastTx(tx)
if err != nil {
t.Fatal(err)
}
mempoolCount += 1
return rec
return rec.Receipt
}
// 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"]
resp, err := client.DumpStorage(addr)
if err != nil {
@ -213,7 +212,7 @@ func getNameRegEntry(t *testing.T, typ string, name string) *types.NameRegEntry
if err != nil {
t.Fatal(err)
}
return entry
return entry.Entry
}
//--------------------------------------------------------------------------------

View File

@ -28,7 +28,7 @@ func testGenPriv(t *testing.T, typ string) {
if err != nil {
t.Fatal(err)
}
if len(privAcc.Address) == 0 {
if len(privAcc.PrivAccount.Address) == 0 {
t.Fatal("Failed to generate an address")
}
}

View File

@ -2,7 +2,6 @@ package rpctest
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"testing"
@ -10,6 +9,7 @@ import (
"github.com/tendermint/tendermint/Godeps/_workspace/src/github.com/gorilla/websocket"
_ "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/types"
"github.com/tendermint/tendermint/wire"
@ -75,14 +75,14 @@ func waitForEvent(t *testing.T, con *websocket.Conn, eventid string, dieOnTimeou
} else {
// if the event id isnt what we're waiting on
// ignore it
var response struct {
Result rpctypes.RPCEventResult `json:"result"`
}
if err := json.Unmarshal(p, &response); err != nil {
var response ctypes.Response
var err error
wire.ReadJSON(&response, p, &err)
if err != nil {
errCh <- err
break
}
if response.Result.Event == eventid {
if response.Result.(*ctypes.ResultEvent).Event == eventid {
goodCh <- p
break
}
@ -109,6 +109,7 @@ func waitForEvent(t *testing.T, con *websocket.Conn, eventid string, dieOnTimeou
// run the check
err := check(eventid, p)
if err != nil {
panic(err)
t.Fatal(err)
}
} else {
@ -124,15 +125,7 @@ func waitForEvent(t *testing.T, con *websocket.Conn, eventid string, dieOnTimeou
func unmarshalResponseNewBlock(b []byte) (*types.Block, error) {
// unmarshall and assert somethings
var response struct {
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 response ctypes.Response
var err error
wire.ReadJSON(&response, b, &err)
if err != nil {
@ -141,7 +134,7 @@ func unmarshalResponseNewBlock(b []byte) (*types.Block, error) {
if response.Error != "" {
return nil, fmt.Errorf(response.Error)
}
block := response.Result.Data
block := response.Result.(*ctypes.ResultEvent).Data.(types.EventDataNewBlock).Block
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 {
return func(eid string, b []byte) error {
// unmarshal and assert correctness
var response struct {
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 response ctypes.Response
var err error
wire.ReadJSON(&response, b, &err)
if err != nil {
@ -209,39 +194,27 @@ func unmarshalValidateSend(amt int64, toAddr []byte) func(string, []byte) error
if response.Error != "" {
return fmt.Errorf(response.Error)
}
if eid != response.Result.Event {
return fmt.Errorf("Eventid is not correct. Got %s, expected %s", response.Result.Event, eid)
if eid != response.Result.(*ctypes.ResultEvent).Event {
return fmt.Errorf("Eventid is not correct. Got %s, expected %s", response.Result.(*ctypes.ResultEvent).Event, eid)
}
tx := response.Result.Data.Tx.(*types.SendTx)
if bytes.Compare(tx.Inputs[0].Address, user[0].Address) != 0 {
tx := response.Result.(*ctypes.ResultEvent).Data.(types.EventDataTx).Tx.(*types.SendTx)
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)
}
if 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 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 {
// unmarshall and assert somethings
var response struct {
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 response ctypes.Response
var err error
wire.ReadJSON(&response, b, &err)
if err != nil {
@ -250,36 +223,31 @@ func unmarshalValidateCall(amt int64, returnCode []byte) func(string, []byte) er
if response.Error != "" {
return fmt.Errorf(response.Error)
}
if response.Result.Data.Exception != "" {
return fmt.Errorf(response.Result.Data.Exception)
var data = response.Result.(*ctypes.ResultEvent).Data.(types.EventDataTx)
if data.Exception != "" {
return fmt.Errorf(data.Exception)
}
tx := response.Result.Data.Tx
if bytes.Compare(tx.Input.Address, user[0].Address) != 0 {
return fmt.Errorf("Senders do not match up! Got %x, expected %x", tx.Input.Address, user[0].Address)
tx := data.Tx.(*types.CallTx)
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)
}
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
if bytes.Compare(ret, returnCode) != 0 {
return fmt.Errorf("Call did not return correctly. Got %x, expected %x", ret, returnCode)
ret := data.Return
if !bytes.Equal(ret, returnCode) {
return fmt.Errorf("Tx did not return correctly. Got %x, expected %x", ret, returnCode)
}
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 {
// unmarshall and assert somethings
var response struct {
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 response ctypes.Response
var err error
wire.ReadJSON(&response, b, &err)
if err != nil {
@ -288,18 +256,21 @@ func unmarshalValidateCallCall(origin, returnCode []byte, txid *[]byte) func(str
if response.Error != "" {
return fmt.Errorf(response.Error)
}
if response.Result.Data.Exception != "" {
return fmt.Errorf(response.Result.Data.Exception)
var data = response.Result.(*ctypes.ResultEvent).Data.(types.EventDataCall)
if data.Exception != "" {
return fmt.Errorf(data.Exception)
}
if bytes.Compare(response.Result.Data.Origin, origin) != 0 {
return fmt.Errorf("Origin does not match up! Got %x, expected %x", response.Result.Data.Origin, origin)
if !bytes.Equal(data.Origin, origin) {
return fmt.Errorf("Origin does not match up! Got %x, expected %x",
data.Origin, origin)
}
ret := response.Result.Data.Return
if bytes.Compare(ret, returnCode) != 0 {
ret := data.Return
if !bytes.Equal(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 {
return fmt.Errorf("TxIDs do not match up! Got %x, expected %x", response.Result.Data.TxID, *txid)
if !bytes.Equal(data.TxID, *txid) {
return fmt.Errorf("TxIDs do not match up! Got %x, expected %x",
data.TxID, *txid)
}
return nil
}

View File

@ -25,9 +25,3 @@ func NewRPCResponse(id string, res interface{}, err string) RPCResponse {
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,
// reward account with bonded coins.
toRelease := []*Validator{}
s.UnbondingValidators.Iterate(func(index int, val *Validator) bool {
toRelease := []*types.Validator{}
s.UnbondingValidators.Iterate(func(index int, val *types.Validator) bool {
if val.UnbondHeight+unbondingPeriodBlocks < block.Height {
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,
// unbond them, they have timed out.
toTimeout := []*Validator{}
s.BondedValidators.Iterate(func(index int, val *Validator) bool {
toTimeout := []*types.Validator{}
s.BondedValidators.Iterate(func(index int, val *types.Validator) bool {
lastActivityHeight := MaxInt(val.BondHeight, val.LastCommitHeight)
if lastActivityHeight+validatorTimeoutBlocks < 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 evc != nil {
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 {
evc.FireEvent(types.EventStringAccOutput(o.Address), types.EventMsgTx{tx, nil, ""})
evc.FireEvent(types.EventStringAccOutput(o.Address), types.EventDataTx{tx, nil, ""})
}
}
return nil
@ -494,8 +494,8 @@ func ExecTx(blockCache *BlockCache, tx types.Tx, runCall bool, evc events.Fireab
if err != nil {
exception = err.Error()
}
evc.FireEvent(types.EventStringAccInput(tx.Input.Address), types.EventMsgTx{tx, ret, exception})
evc.FireEvent(types.EventStringAccOutput(tx.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.EventDataTx{tx, ret, exception})
}
} else {
// 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)
}
// Add ValidatorInfo
_s.SetValidatorInfo(&ValidatorInfo{
_s.SetValidatorInfo(&types.ValidatorInfo{
Address: tx.PubKey.Address(),
PubKey: tx.PubKey,
UnbondTo: tx.UnbondTo,
@ -699,7 +699,7 @@ func ExecTx(blockCache *BlockCache, tx types.Tx, runCall bool, evc events.Fireab
FirstBondAmount: outTotal,
})
// Add Validator
added := _s.BondedValidators.Add(&Validator{
added := _s.BondedValidators.Add(&types.Validator{
Address: tx.PubKey.Address(),
PubKey: tx.PubKey,
BondHeight: _s.LastBlockHeight + 1,
@ -893,7 +893,7 @@ func ExecTx(blockCache *BlockCache, tx types.Tx, runCall bool, evc events.Fireab
}
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)
}
@ -981,3 +981,14 @@ func hasBondOrSendPermission(state AccountGetter, accs map[string]*acm.Account)
}
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"
ptypes "github.com/tendermint/tendermint/permission/types"
. "github.com/tendermint/tendermint/state/types"
)
var chain_id = "lone_ranger"

View File

@ -12,6 +12,7 @@ import (
dbm "github.com/tendermint/tendermint/db"
"github.com/tendermint/tendermint/events"
ptypes "github.com/tendermint/tendermint/permission/types"
. "github.com/tendermint/tendermint/state/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) {
case types.EventMsgTx:
case types.EventDataTx:
return ev, ev.Exception
case types.EventMsgCall:
case types.EventDataCall:
return ev, ev.Exception
case string:
return nil, ev
@ -1118,7 +1119,7 @@ func testSNativeCALL(t *testing.T, expectPass bool, blockCache *BlockCache, doug
if exception != "" {
t.Fatal("Unexpected exception", exception)
}
evv := ev.(types.EventMsgCall)
evv := ev.(types.EventDataCall)
ret := evv.Return
if err := f(ret); err != nil {
t.Fatal(err)

View File

@ -3,15 +3,18 @@ package state
import (
"bytes"
"io"
"io/ioutil"
"time"
acm "github.com/tendermint/tendermint/account"
"github.com/tendermint/tendermint/wire"
. "github.com/tendermint/tendermint/common"
dbm "github.com/tendermint/tendermint/db"
"github.com/tendermint/tendermint/events"
"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/wire"
)
var (
@ -32,9 +35,9 @@ type State struct {
LastBlockHash []byte
LastBlockParts types.PartSetHeader
LastBlockTime time.Time
BondedValidators *ValidatorSet
LastBondedValidators *ValidatorSet
UnbondingValidators *ValidatorSet
BondedValidators *types.ValidatorSet
LastBondedValidators *types.ValidatorSet
UnbondingValidators *types.ValidatorSet
accounts merkle.Tree // Shouldn't be accessed directly.
validatorInfos 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.LastBlockParts = wire.ReadBinary(types.PartSetHeader{}, r, n, err).(types.PartSetHeader)
s.LastBlockTime = wire.ReadTime(r, n, err)
s.BondedValidators = wire.ReadBinary(&ValidatorSet{}, r, n, err).(*ValidatorSet)
s.LastBondedValidators = wire.ReadBinary(&ValidatorSet{}, r, n, err).(*ValidatorSet)
s.UnbondingValidators = wire.ReadBinary(&ValidatorSet{}, r, n, err).(*ValidatorSet)
s.BondedValidators = wire.ReadBinary(&types.ValidatorSet{}, r, n, err).(*types.ValidatorSet)
s.LastBondedValidators = wire.ReadBinary(&types.ValidatorSet{}, r, n, err).(*types.ValidatorSet)
s.UnbondingValidators = wire.ReadBinary(&types.ValidatorSet{}, r, n, err).(*types.ValidatorSet)
accountsHash := wire.ReadByteSlice(r, n, err)
s.accounts = merkle.NewIAVLTree(wire.BasicCodec, acm.AccountCodec, defaultAccountsCacheCapacity, db)
s.accounts.Load(accountsHash)
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)
nameRegHash := wire.ReadByteSlice(r, n, err)
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
// has no side effects.
func (s *State) GetValidatorInfo(address []byte) *ValidatorInfo {
func (s *State) GetValidatorInfo(address []byte) *types.ValidatorInfo {
_, valInfo := s.validatorInfos.Get(address)
if valInfo == nil {
return nil
}
return valInfo.(*ValidatorInfo).Copy()
return valInfo.(*types.ValidatorInfo).Copy()
}
// Returns false if new, true if updated.
// The valInfo is copied before setting, so mutating it
// 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())
}
@ -219,7 +222,7 @@ func (s *State) GetValidatorInfos() merkle.Tree {
return s.validatorInfos.Copy()
}
func (s *State) unbondValidator(val *Validator) {
func (s *State) unbondValidator(val *types.Validator) {
// Move validator to UnbondingValidators
val, removed := s.BondedValidators.Remove(val.Address)
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
val, removed := s.UnbondingValidators.Remove(val.Address)
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
valInfo := s.GetValidatorInfo(val.Address)
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
valInfo := s.GetValidatorInfo(val.Address)
if valInfo == nil {
@ -360,12 +363,114 @@ func (s *State) SetFireable(evc events.Fireable) {
}
//-----------------------------------------------------------------------------
// Genesis
type InvalidTxError struct {
Tx types.Tx
Reason error
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 (txErr InvalidTxError) Error() string {
return Fmt("Invalid tx: [%v] reason: [%v]", txErr.Tx, txErr.Reason)
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, 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
import (
"bytes"
"sort"
"time"
acm "github.com/tendermint/tendermint/account"
. "github.com/tendermint/tendermint/common"
dbm "github.com/tendermint/tendermint/db"
ptypes "github.com/tendermint/tendermint/permission/types"
. "github.com/tendermint/tendermint/state/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) {
privAccount := acm.GenPrivAccount()
perms := ptypes.DefaultAccountPermissions
@ -39,37 +28,7 @@ func RandAccount(randBalance bool, minBalance int64) (*acm.Account, *acm.PrivAcc
return acc, privAccount
}
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: []*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) {
func RandGenesisDoc(numAccounts int, randBalance bool, minBalance int64, numValidators int, randBonded bool, minBonded int64) (*GenesisDoc, []*acm.PrivAccount, []*types.PrivValidator) {
accounts := make([]GenesisAccount, numAccounts)
privAccounts := make([]*acm.PrivAccount, numAccounts)
defaultPerms := ptypes.DefaultAccountPermissions
@ -83,9 +42,9 @@ func RandGenesisDoc(numAccounts int, randBalance bool, minBalance int64, numVali
privAccounts[i] = privAccount
}
validators := make([]GenesisValidator, numValidators)
privValidators := make([]*PrivValidator, numValidators)
privValidators := make([]*types.PrivValidator, numValidators)
for i := 0; i < numValidators; i++ {
valInfo, _, privVal := RandValidator(randBonded, minBonded)
valInfo, _, privVal := types.RandValidator(randBonded, minBonded)
validators[i] = GenesisValidator{
PubKey: valInfo.PubKey,
Amount: valInfo.FirstBondAmount,
@ -98,7 +57,7 @@ func RandGenesisDoc(numAccounts int, randBalance bool, minBalance int64, numVali
}
privValidators[i] = privVal
}
sort.Sort(PrivValidatorsByAddress(privValidators))
sort.Sort(types.PrivValidatorsByAddress(privValidators))
return &GenesisDoc{
GenesisTime: time.Now(),
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()
genDoc, privAccounts, privValidators := RandGenesisDoc(numAccounts, randBalance, minBalance, numValidators, randBonded, minBonded)
s0 := MakeGenesisState(db, genDoc)
s0.Save()
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
accounts map[Word256]vmAccountInfo
storages map[Tuple256]Word256
logs []*vm.Log
logs []types.EventDataLog
}
func NewTxCache(backend *BlockCache) *TxCache {
@ -20,7 +20,7 @@ func NewTxCache(backend *BlockCache) *TxCache {
backend: backend,
accounts: make(map[Word256]vmAccountInfo),
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)
}

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 (
"fmt"
. "github.com/tendermint/tendermint/common"
"github.com/tendermint/tendermint/wire"
)
// Functions to generate eventId strings
@ -18,15 +21,50 @@ func EventStringDupeout() string { return "Dupeout" }
func EventStringNewBlock() string { return "NewBlock" }
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)
// 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"`
Return []byte `json:"return"`
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 {
Caller []byte `json:"caller"`
Callee []byte `json:"callee"`
@ -35,10 +73,10 @@ type CallData struct {
Gas int64 `json:"gas"`
}
type EventMsgCall struct {
CallData *CallData `json:"call_data"`
Origin []byte `json:"origin"`
TxID []byte `json:"tx_id"`
Return []byte `json:"return"`
Exception string `json:"exception"`
// EventDataLog fires when a contract executes the LOG opcode
type EventDataLog struct {
Address Word256 `json:"address"`
Topics []Word256 `json:"topics"`
Data []byte `json:"data"`
Height int64 `json:"height"`
}

View File

@ -1,6 +1,7 @@
package state
package types
import (
"bytes"
"errors"
"fmt"
"io/ioutil"
@ -8,10 +9,8 @@ import (
"sync"
acm "github.com/tendermint/tendermint/account"
"github.com/tendermint/tendermint/wire"
. "github.com/tendermint/tendermint/common"
. "github.com/tendermint/tendermint/consensus/types"
"github.com/tendermint/tendermint/types"
"github.com/tendermint/tendermint/wire"
"github.com/tendermint/tendermint/Godeps/_workspace/src/github.com/tendermint/ed25519"
)
@ -23,11 +22,11 @@ const (
stepPrecommit = 3
)
func voteToStep(vote *types.Vote) int8 {
func voteToStep(vote *Vote) int8 {
switch vote.Type {
case types.VoteTypePrevote:
case VoteTypePrevote:
return stepPrevote
case types.VoteTypePrecommit:
case VoteTypePrecommit:
return stepPrecommit
default:
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()
defer privVal.mtx.Unlock()
@ -135,7 +134,7 @@ func (privVal *PrivValidator) SignVote(chainID string, vote *types.Vote) error {
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)
}
@ -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()
defer privVal.mtx.Unlock()
if privVal.LastHeight < rebondTx.Height {
@ -183,3 +182,21 @@ func (privVal *PrivValidator) SignRebondTx(chainID string, rebondTx *types.Rebon
func (privVal *PrivValidator) String() string {
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 (
"errors"
@ -6,9 +6,8 @@ import (
"io"
acm "github.com/tendermint/tendermint/account"
"github.com/tendermint/tendermint/wire"
. "github.com/tendermint/tendermint/common"
"github.com/tendermint/tendermint/types"
"github.com/tendermint/tendermint/wire"
)
var (
@ -19,12 +18,12 @@ var (
type Proposal struct {
Height int `json:"height"`
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.
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{
Height: height,
Round: round,

View File

@ -1,4 +1,4 @@
package consensus
package types
import (
"testing"
@ -6,14 +6,13 @@ import (
acm "github.com/tendermint/tendermint/account"
. "github.com/tendermint/tendermint/common"
_ "github.com/tendermint/tendermint/config/tendermint_test"
"github.com/tendermint/tendermint/types"
)
func TestProposalSignable(t *testing.T) {
proposal := &Proposal{
Height: 12345,
Round: 23456,
BlockPartsHeader: types.PartSetHeader{111, []byte("blockparts")},
BlockPartsHeader: PartSetHeader{111, []byte("blockparts")},
POLRound: -1,
}
signBytes := acm.SignBytes(config.GetString("chain_id"), proposal)

View File

@ -1,4 +1,4 @@
package state
package types
import (
"bytes"
@ -6,16 +6,15 @@ import (
"io"
acm "github.com/tendermint/tendermint/account"
"github.com/tendermint/tendermint/wire"
. "github.com/tendermint/tendermint/common"
"github.com/tendermint/tendermint/types"
"github.com/tendermint/tendermint/wire"
)
// Persistent (mostly) static data for each Validator
type ValidatorInfo struct {
Address []byte `json:"address"`
PubKey acm.PubKeyEd25519 `json:"pub_key"`
UnbondTo []*types.TxOutput `json:"unbond_to"`
UnbondTo []*TxOutput `json:"unbond_to"`
FirstBondHeight int `json:"first_bond_height"`
FirstBondAmount int64 `json:"first_bond_amount"`
DestroyedHeight int `json:"destroyed_height"` // If destroyed

View File

@ -1,4 +1,4 @@
package state
package types
import (
"bytes"
@ -9,7 +9,6 @@ import (
"github.com/tendermint/tendermint/account"
. "github.com/tendermint/tendermint/common"
"github.com/tendermint/tendermint/merkle"
"github.com/tendermint/tendermint/types"
)
// 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
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) {
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 {
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)
}
_, val := valSet.GetByIndex(idx)

View File

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

View File

@ -1,4 +1,4 @@
package consensus
package types
import (
"bytes"
@ -7,10 +7,8 @@ import (
"sync"
acm "github.com/tendermint/tendermint/account"
"github.com/tendermint/tendermint/wire"
. "github.com/tendermint/tendermint/common"
sm "github.com/tendermint/tendermint/state"
"github.com/tendermint/tendermint/types"
"github.com/tendermint/tendermint/wire"
)
// VoteSet helps collect signatures from validators at each height+round
@ -24,18 +22,18 @@ type VoteSet struct {
type_ byte
mtx sync.Mutex
valSet *sm.ValidatorSet
votes []*types.Vote // validator index -> vote
valSet *ValidatorSet
votes []*Vote // validator index -> vote
votesBitArray *BitArray // validator index -> has vote?
votesByBlock map[string]int64 // string(blockHash)+string(blockParts) -> vote sum.
totalVotes int64
maj23Hash []byte
maj23Parts types.PartSetHeader
maj23Parts PartSetHeader
maj23Exists bool
}
// 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 {
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,
type_: type_,
valSet: valSet,
votes: make([]*types.Vote, valSet.Size()),
votes: make([]*Vote, valSet.Size()),
votesBitArray: NewBitArray(valSet.Size()),
votesByBlock: make(map[string]int64),
totalVotes: 0,
@ -87,7 +85,7 @@ func (voteSet *VoteSet) Size() int {
// Otherwise returns err=ErrVote[UnexpectedStep|InvalidAccount|InvalidSignature|InvalidBlockHash|ConflictingSignature]
// Duplicate votes return added=false, err=nil.
// 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()
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]
// Duplicate votes return added=false, err=nil.
// 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()
defer voteSet.mtx.Unlock()
// Ensure that signer is a validator.
valIndex, val := voteSet.valSet.GetByAddress(address)
if val == nil {
return false, 0, types.ErrVoteInvalidAccount
return false, 0, ErrVoteInvalidAccount
}
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.
_, val := voteSet.valSet.GetByIndex(valIndex)
if val == nil {
return false, 0, types.ErrVoteInvalidAccount
return false, 0, ErrVoteInvalidAccount
}
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)
if (vote.Height != voteSet.height) ||
(vote.Round != voteSet.round) ||
(vote.Type != voteSet.type_) {
return false, 0, types.ErrVoteUnexpectedStep
return false, 0, ErrVoteUnexpectedStep
}
// Check signature.
if !val.PubKey.VerifyBytes(acm.SignBytes(config.GetString("chain_id"), vote), vote.Signature) {
// Bad signature.
return false, 0, types.ErrVoteInvalidSignature
return false, 0, ErrVoteInvalidSignature
}
// 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) {
return false, valIndex, nil
} else {
return false, valIndex, &types.ErrVoteConflictingSignature{
return false, valIndex, &ErrVoteConflictingSignature{
VoteA: existingVote,
VoteB: vote,
}
@ -176,13 +174,13 @@ func (voteSet *VoteSet) BitArray() *BitArray {
return voteSet.votesBitArray.Copy()
}
func (voteSet *VoteSet) GetByIndex(valIndex int) *types.Vote {
func (voteSet *VoteSet) GetByIndex(valIndex int) *Vote {
voteSet.mtx.Lock()
defer voteSet.mtx.Unlock()
return voteSet.votes[valIndex]
}
func (voteSet *VoteSet) GetByAddress(address []byte) *types.Vote {
func (voteSet *VoteSet) GetByAddress(address []byte) *Vote {
voteSet.mtx.Lock()
defer voteSet.mtx.Unlock()
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.
// 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()
defer voteSet.mtx.Unlock()
if voteSet.maj23Exists {
return voteSet.maj23Hash, voteSet.maj23Parts, true
} else {
return nil, types.PartSetHeader{}, false
return nil, PartSetHeader{}, false
}
}
@ -271,17 +269,17 @@ func (voteSet *VoteSet) StringShort() string {
//--------------------------------------------------------------------------------
// Validation
func (voteSet *VoteSet) MakeValidation() *types.Validation {
if voteSet.type_ != types.VoteTypePrecommit {
PanicSanity("Cannot MakeValidation() unless VoteSet.Type is types.VoteTypePrecommit")
func (voteSet *VoteSet) MakeValidation() *Validation {
if voteSet.type_ != VoteTypePrecommit {
PanicSanity("Cannot MakeValidation() unless VoteSet.Type is VoteTypePrecommit")
}
voteSet.mtx.Lock()
defer voteSet.mtx.Unlock()
if len(voteSet.maj23Hash) == 0 {
PanicSanity("Cannot MakeValidation() unless a blockhash has +2/3")
}
precommits := make([]*types.Vote, voteSet.valSet.Size())
voteSet.valSet.Iterate(func(valIndex int, val *sm.Validator) bool {
precommits := make([]*Vote, voteSet.valSet.Size())
voteSet.valSet.Iterate(func(valIndex int, val *Validator) bool {
vote := voteSet.votes[valIndex]
if vote == nil {
return false
@ -295,7 +293,40 @@ func (voteSet *VoteSet) MakeValidation() *types.Validation {
precommits[valIndex] = vote
return false
})
return &types.Validation{
return &Validation{
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 (
"bytes"
"sort"
. "github.com/tendermint/tendermint/common"
. "github.com/tendermint/tendermint/common/test"
_ "github.com/tendermint/tendermint/config/tendermint_test"
sm "github.com/tendermint/tendermint/state"
"github.com/tendermint/tendermint/types"
"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
func withHeight(vote *types.Vote, height int) *types.Vote {
func withHeight(vote *Vote, height int) *Vote {
vote = vote.Copy()
vote.Height = height
return vote
}
// 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.Round = round
return vote
}
// 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.Type = type_
return vote
}
// 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.BlockHash = blockHash
return vote
}
// 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.BlockParts = blockParts
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)
added, _, err := voteSet.AddByAddress(privVal.Address, vote)
return added, err
@ -57,7 +67,7 @@ func signAddVote(privVal *sm.PrivValidator, vote *types.Vote, voteSet *VoteSet)
func TestAddVote(t *testing.T) {
height, round := 1, 0
voteSet, _, privValidators := randVoteSet(height, round, types.VoteTypePrevote, 10, 1)
voteSet, _, privValidators := randVoteSet(height, round, VoteTypePrevote, 10, 1)
val0 := privValidators[0]
// t.Logf(">> %v", voteSet)
@ -73,7 +83,7 @@ func TestAddVote(t *testing.T) {
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)
if voteSet.GetByAddress(val0.Address) == nil {
@ -90,9 +100,9 @@ func TestAddVote(t *testing.T) {
func Test2_3Majority(t *testing.T) {
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.
for i := 0; i < 6; i++ {
@ -124,13 +134,13 @@ func Test2_3Majority(t *testing.T) {
func Test2_3MajorityRedux(t *testing.T) {
height, round := 1, 0
voteSet, _, privValidators := randVoteSet(height, round, types.VoteTypePrevote, 100, 1)
voteSet, _, privValidators := randVoteSet(height, round, VoteTypePrevote, 100, 1)
blockHash := CRandBytes(32)
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.
for i := 0; i < 66; i++ {
@ -152,7 +162,7 @@ func Test2_3MajorityRedux(t *testing.T) {
// 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)
hash, header, ok = voteSet.TwoThirdsMajority()
if hash != nil || !header.IsZero() || ok {
@ -162,7 +172,7 @@ func Test2_3MajorityRedux(t *testing.T) {
// 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)
hash, header, ok = voteSet.TwoThirdsMajority()
if hash != nil || !header.IsZero() || ok {
@ -191,10 +201,10 @@ func Test2_3MajorityRedux(t *testing.T) {
func TestBadVotes(t *testing.T) {
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.
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)
if !added || err != nil {
t.Errorf("Expected VoteSet.Add to succeed")
@ -219,7 +229,7 @@ func TestBadVotes(t *testing.T) {
}
// 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 {
t.Errorf("Expected VoteSet.Add to fail, wrong type")
}
@ -227,10 +237,10 @@ func TestBadVotes(t *testing.T) {
func TestMakeValidation(t *testing.T) {
height, round := 1, 0
voteSet, _, privValidators := randVoteSet(height, round, types.VoteTypePrecommit, 10, 1)
blockHash, blockParts := CRandBytes(32), types.PartSetHeader{123, CRandBytes(32)}
voteSet, _, privValidators := randVoteSet(height, round, VoteTypePrecommit, 10, 1)
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}
// 6 out of 10 voted for some block.
@ -244,7 +254,7 @@ func TestMakeValidation(t *testing.T) {
// 7th voted for some other block.
{
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)
}

View File

@ -2,6 +2,7 @@ package vm
import (
. "github.com/tendermint/tendermint/common"
"github.com/tendermint/tendermint/types"
. "github.com/tendermint/tendermint/vm"
"github.com/tendermint/tendermint/vm/sha3"
)
@ -9,7 +10,7 @@ import (
type FakeAppState struct {
accounts map[string]*Account
storage map[string]Word256
logs []*Log
logs []types.EventDataLog
}
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
}
func (fas *FakeAppState) AddLog(log *Log) {
func (fas *FakeAppState) AddLog(log types.EventDataLog) {
fas.logs = append(fas.logs, log)
}

View File

@ -45,7 +45,7 @@ func TestLog4(t *testing.T) {
doneChan := make(chan struct{}, 1)
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
if !reflect.DeepEqual(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
switch ev := msg.(type) {
case types.EventMsgTx:
case types.EventDataTx:
return ev.Exception
case types.EventMsgCall:
case types.EventDataCall:
return ev.Exception
case string:
return ev

View File

@ -3,6 +3,7 @@ package vm
import (
. "github.com/tendermint/tendermint/common"
ptypes "github.com/tendermint/tendermint/permission/types"
"github.com/tendermint/tendermint/types"
)
const (
@ -27,15 +28,6 @@ func (acc *Account) String() string {
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 {
// Accounts
@ -49,7 +41,7 @@ type AppState interface {
SetStorage(Word256, Word256, Word256) // Setting to Zero is deleting.
// Logs
AddLog(*Log)
AddLog(types.EventDataLog)
}
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) {
// fire the post call event (including exception if applicable)
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},
vm.origin.Postfix(20),
vm.txid,
@ -694,7 +694,7 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
if !ok {
return nil, firstErr(err, ErrMemoryOutOfBounds)
}
log := &Log{
log := types.EventDataLog{
callee.Address,
topics,
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
// (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) {
// Get typeInfo

View File

@ -71,6 +71,7 @@ func ReadJSONPtr(o interface{}, bytes []byte, err *error) interface{} {
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{} {
rv, rt := reflect.ValueOf(o), reflect.TypeOf(o)
if rv.Kind() == reflect.Ptr {