diff --git a/cmd/daemon.go b/cmd/daemon.go index fca8b46a0..4d757cfea 100644 --- a/cmd/daemon.go +++ b/cmd/daemon.go @@ -22,8 +22,8 @@ type Node struct { pexReactor *p2p.PEXReactor blockStore *block.BlockStore mempoolReactor *mempool_.MempoolReactor + consensusState *consensus.ConsensusState consensusReactor *consensus.ConsensusReactor - state *state_.State privValidator *state_.PrivValidator } @@ -58,7 +58,8 @@ func NewNode() *Node { mempoolReactor := mempool_.NewMempoolReactor(mempool) // Get ConsensusReactor - consensusReactor := consensus.NewConsensusReactor(blockStore, mempoolReactor, state) + consensusState := consensus.NewConsensusState(state, blockStore, mempoolReactor) + consensusReactor := consensus.NewConsensusReactor(consensusState, blockStore) if privValidator != nil { consensusReactor.SetPrivValidator(privValidator) } @@ -71,8 +72,8 @@ func NewNode() *Node { pexReactor: pexReactor, blockStore: blockStore, mempoolReactor: mempoolReactor, + consensusState: consensusState, consensusReactor: consensusReactor, - state: state, privValidator: privValidator, } } @@ -144,7 +145,7 @@ func daemon() { // Run the RPC server. if config.App.GetString("RPC.HTTP.ListenAddr") != "" { rpc.SetRPCBlockStore(n.blockStore) - rpc.SetRPCState(n.state) + rpc.SetRPCConsensusState(n.consensusState) rpc.SetRPCMempoolReactor(n.mempoolReactor) rpc.StartHTTPServer() } diff --git a/consensus/reactor.go b/consensus/reactor.go index 0e29481ec..9ccf53e50 100644 --- a/consensus/reactor.go +++ b/consensus/reactor.go @@ -12,7 +12,6 @@ import ( . "github.com/tendermint/tendermint/block" . "github.com/tendermint/tendermint/common" . "github.com/tendermint/tendermint/consensus/types" - "github.com/tendermint/tendermint/mempool" "github.com/tendermint/tendermint/p2p" "github.com/tendermint/tendermint/state" ) @@ -39,12 +38,11 @@ type ConsensusReactor struct { conS *ConsensusState } -func NewConsensusReactor(blockStore *BlockStore, mempoolReactor *mempool.MempoolReactor, state *state.State) *ConsensusReactor { - conS := NewConsensusState(state, blockStore, mempoolReactor) +func NewConsensusReactor(consensusState *ConsensusState, blockStore *BlockStore) *ConsensusReactor { conR := &ConsensusReactor{ blockStore: blockStore, quit: make(chan struct{}), - conS: conS, + conS: consensusState, } return conR } diff --git a/consensus/state.go b/consensus/state.go index ac6700018..fcc538222 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -259,6 +259,12 @@ func NewConsensusState(state *state.State, blockStore *BlockStore, mempoolReacto return cs } +func (cs *ConsensusState) GetState() *state.State { + cs.mtx.Lock() + defer cs.mtx.Unlock() + return cs.state.Copy() +} + func (cs *ConsensusState) GetRoundState() *RoundState { cs.mtx.Lock() defer cs.mtx.Unlock() diff --git a/rpc/account.go b/rpc/account.go index 4c07bf3b0..f05ada22f 100644 --- a/rpc/account.go +++ b/rpc/account.go @@ -54,3 +54,18 @@ func SignSendTxHandler(w http.ResponseWriter, r *http.Request) { } WriteAPIResponse(w, API_OK, res) } + +//----------------------------------------------------------------------------- + +type ListAccountsResponse struct { + Accounts []*account.Account +} + +func ListAccountsHandler(w http.ResponseWriter, r *http.Request) { + state := consensusState.GetState() + state.GetAccounts().Iterate(func(key interface{}, value interface{}) bool { + log.Warn(">>", "key", key, "value", value) + return false + }) + WriteAPIResponse(w, API_OK, state) +} diff --git a/rpc/http_server.go b/rpc/http_server.go index 774f0c5e9..a53c40220 100644 --- a/rpc/http_server.go +++ b/rpc/http_server.go @@ -14,6 +14,7 @@ func StartHTTPServer() { http.HandleFunc("/broadcast_tx", BroadcastTxHandler) http.HandleFunc("/gen_priv_account", GenPrivAccountHandler) http.HandleFunc("/sign_send_tx", SignSendTxHandler) + http.HandleFunc("/accounts", ListAccountsHandler) log.Info(Fmt("Starting RPC HTTP server on %s", config.App.GetString("RPC.HTTP.ListenAddr"))) diff --git a/rpc/rpc.go b/rpc/rpc.go index 1568c4ad4..61c8ad567 100644 --- a/rpc/rpc.go +++ b/rpc/rpc.go @@ -2,20 +2,20 @@ package rpc import ( block_ "github.com/tendermint/tendermint/block" + "github.com/tendermint/tendermint/consensus" mempool_ "github.com/tendermint/tendermint/mempool" - state_ "github.com/tendermint/tendermint/state" ) var blockStore *block_.BlockStore -var state *state_.State +var consensusState *consensus.ConsensusState var mempoolReactor *mempool_.MempoolReactor func SetRPCBlockStore(bs *block_.BlockStore) { blockStore = bs } -func SetRPCState(s *state_.State) { - state = s +func SetRPCConsensusState(cs *consensus.ConsensusState) { + consensusState = cs } func SetRPCMempoolReactor(mr *mempool_.MempoolReactor) { diff --git a/state/state.go b/state/state.go index e03bdcc66..5ba6aacc5 100644 --- a/state/state.go +++ b/state/state.go @@ -254,7 +254,7 @@ func (s *State) ExecTx(tx_ Tx) error { // Good! Adjust accounts s.AdjustByInputs(accounts, tx.Inputs) s.AdjustByOutputs(accounts, tx.Outputs) - s.SetAccounts(accounts) + s.UpdateAccounts(accounts) return nil case *BondTx: @@ -289,7 +289,7 @@ func (s *State) ExecTx(tx_ Tx) error { // Good! Adjust accounts s.AdjustByInputs(accounts, tx.Inputs) - s.SetAccounts(accounts) + s.UpdateAccounts(accounts) // Add ValidatorInfo s.SetValidatorInfo(&ValidatorInfo{ Address: tx.PubKey.Address(), @@ -355,8 +355,6 @@ func (s *State) ExecTx(tx_ Tx) error { return errors.New("Invalid rebond height") } - // tx.Height must be - // Good! s.rebondValidator(val) return nil @@ -444,7 +442,7 @@ func (s *State) releaseValidator(val *Validator) { panic("Couldn't get or make unbondTo accounts") } s.AdjustByOutputs(accounts, valInfo.UnbondTo) - s.SetAccounts(accounts) + s.UpdateAccounts(accounts) // Remove validator from UnbondingValidators _, removed := s.UnbondingValidators.Remove(val.Address) @@ -612,15 +610,21 @@ func (s *State) GetAccount(address []byte) *Account { return account.(*Account).Copy() } +// The returned Account is a copy, so mutating it +// has no side effects. +func (s *State) GetAccounts() merkle.Tree { + return s.accounts.Copy() +} + // The account is copied before setting, so mutating it // afterwards has no side effects. -func (s *State) SetAccount(account *Account) { +func (s *State) UpdateAccount(account *Account) { s.accounts.Set(account.Address, account.Copy()) } // The accounts are copied before setting, so mutating it // afterwards has no side effects. -func (s *State) SetAccounts(accounts map[string]*Account) { +func (s *State) UpdateAccounts(accounts map[string]*Account) { for _, account := range accounts { s.accounts.Set(account.Address, account.Copy()) } diff --git a/state/state_test.go b/state/state_test.go index c2d81814c..4158e1d43 100644 --- a/state/state_test.go +++ b/state/state_test.go @@ -36,7 +36,7 @@ func TestCopyState(t *testing.T) { } // Setting, however, should change the balance. - s0.SetAccount(acc) + s0.UpdateAccount(acc) if s0.GetAccount(acc0Address).Balance != acc.Balance { t.Error("Account balance wasn't set") }