diff --git a/erisdb/config.go b/erisdb/config.go new file mode 100644 index 0000000000000000000000000000000000000000..438d6231227564f6223e8352226bb1ef76407d27 --- /dev/null +++ b/erisdb/config.go @@ -0,0 +1,13 @@ +package erisdb + +import ( + cfg "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/config" +) + +var config cfg.Config + +func init() { + cfg.OnConfig(func(newConfig cfg.Config) { + config = newConfig + }) +} diff --git a/erisdb/pipe/accounts.go b/erisdb/pipe/accounts.go index 94dfbad9a9a2aa945f929cbf7cfc79e5cecdded4..a12c8049f5542d252792b62cbc8b4a1ff5b95902 100644 --- a/erisdb/pipe/accounts.go +++ b/erisdb/pipe/accounts.go @@ -4,21 +4,21 @@ import ( "bytes" "encoding/hex" "fmt" + "sync" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/account" cmn "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common" - cs "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus" - mempl "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/mempool" - "sync" + + "github.com/eris-ltd/eris-db/tmsp" ) // The accounts struct has methods for working with accounts. type accounts struct { - consensusState *cs.ConsensusState - mempoolReactor *mempl.MempoolReactor - filterFactory *FilterFactory + erisdbApp *tmsp.ErisDBApp + filterFactory *FilterFactory } -func newAccounts(consensusState *cs.ConsensusState, mempoolReactor *mempl.MempoolReactor) *accounts { +func newAccounts(erisdbApp *tmsp.ErisDBApp) *accounts { ff := NewFilterFactory() ff.RegisterFilterPool("code", &sync.Pool{ @@ -33,7 +33,7 @@ func newAccounts(consensusState *cs.ConsensusState, mempoolReactor *mempl.Mempoo }, }) - return &accounts{consensusState, mempoolReactor, ff} + return &accounts{erisdbApp, ff} } @@ -56,7 +56,7 @@ func (this *accounts) GenPrivAccountFromKey(privKey []byte) (*account.PrivAccoun // Get all accounts. func (this *accounts) Accounts(fda []*FilterData) (*AccountList, error) { accounts := make([]*account.Account, 0) - state := this.consensusState.GetState() + state := this.erisdbApp.GetState() filter, err := this.filterFactory.NewFilter(fda) if err != nil { return nil, fmt.Errorf("Error in query: " + err.Error()) @@ -73,7 +73,7 @@ func (this *accounts) Accounts(fda []*FilterData) (*AccountList, error) { // Get an account. func (this *accounts) Account(address []byte) (*account.Account, error) { - cache := this.mempoolReactor.Mempool.GetCache() + cache := this.erisdbApp.GetState() // NOTE: we want to read from mempool! acc := cache.GetAccount(address) if acc == nil { acc = this.newAcc(address) @@ -85,7 +85,7 @@ func (this *accounts) Account(address []byte) (*account.Account, error) { // Both the key and value is returned. func (this *accounts) StorageAt(address, key []byte) (*StorageItem, error) { - state := this.consensusState.GetState() + state := this.erisdbApp.GetState() account := state.GetAccount(address) if account == nil { return &StorageItem{key, []byte{}}, nil @@ -103,7 +103,7 @@ func (this *accounts) StorageAt(address, key []byte) (*StorageItem, error) { // Get the storage of the account with address 'address'. func (this *accounts) Storage(address []byte) (*Storage, error) { - state := this.consensusState.GetState() + state := this.erisdbApp.GetState() account := state.GetAccount(address) storageItems := make([]StorageItem, 0) if account == nil { diff --git a/erisdb/pipe/blockchain.go b/erisdb/pipe/blockchain.go index 2f564135289e1735ee2d73dbf70e9d333a0a6865..e11dc69082bc2af64ee9cc67d5d7e19906ab34b2 100644 --- a/erisdb/pipe/blockchain.go +++ b/erisdb/pipe/blockchain.go @@ -2,7 +2,6 @@ package pipe import ( "fmt" - bc "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/blockchain" dbm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/db" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/state" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types" @@ -14,13 +13,19 @@ import ( const BLOCK_MAX = 50 +type BlockStore interface { + Height() int + LoadBlockMeta(height int) *types.BlockMeta + LoadBlock(height int) *types.Block +} + // The blockchain struct. type blockchain struct { - blockStore *bc.BlockStore + blockStore BlockStore filterFactory *FilterFactory } -func newBlockchain(blockStore *bc.BlockStore) *blockchain { +func newBlockchain(blockStore BlockStore) *blockchain { ff := NewFilterFactory() ff.RegisterFilterPool("height", &sync.Pool{ diff --git a/erisdb/pipe/consensus.go b/erisdb/pipe/consensus.go index 1ca1f47206d56bc43526983aa344b172bd4b3123..69f1a7a5e8aa4b131a76ae09faf01e460b0d3e13 100644 --- a/erisdb/pipe/consensus.go +++ b/erisdb/pipe/consensus.go @@ -1,34 +1,24 @@ package pipe import ( - cm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus" - "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types" - "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/wire" + + "github.com/eris-ltd/eris-db/tmsp" ) // The consensus struct. type consensus struct { - consensusState *cm.ConsensusState - p2pSwitch *p2p.Switch + erisdbApp *tmsp.ErisDBApp } -func newConsensus(consensusState *cm.ConsensusState, p2pSwitch *p2p.Switch) *consensus { - return &consensus{consensusState, p2pSwitch} +func newConsensus(erisdbApp *tmsp.ErisDBApp) *consensus { + return &consensus{erisdbApp} } // Get the current consensus state. func (this *consensus) State() (*ConsensusState, error) { - roundState := this.consensusState.GetRoundState() - peerRoundStates := []string{} - for _, peer := range this.p2pSwitch.Peers().List() { - // TODO: clean this up? - peerState := peer.Data.Get(cm.PeerStateKey).(*cm.PeerState) - peerRoundState := peerState.GetRoundState() - peerRoundStateStr := peer.Key + ":" + string(wire.JSONBytes(peerRoundState)) - peerRoundStates = append(peerRoundStates, peerRoundStateStr) - } - return FromRoundState(roundState), nil + // TODO-RPC! + return &ConsensusState{}, nil } // Get all validators. @@ -37,7 +27,7 @@ func (this *consensus) Validators() (*ValidatorList, error) { bondedValidators := make([]*types.Validator, 0) unbondingValidators := make([]*types.Validator, 0) - s := this.consensusState.GetState() + s := this.erisdbApp.GetState() blockHeight = s.LastBlockHeight s.BondedValidators.Iterate(func(index int, val *types.Validator) bool { bondedValidators = append(bondedValidators, val) diff --git a/erisdb/pipe/namereg.go b/erisdb/pipe/namereg.go index 1fe22dbb51b3df3a6abd9d2ac9b0d3a555d9bd83..a8e3a6ad82813e73d78fea1f91bf3f491bc5843d 100644 --- a/erisdb/pipe/namereg.go +++ b/erisdb/pipe/namereg.go @@ -4,19 +4,21 @@ import ( "bytes" "encoding/hex" "fmt" - cm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus" + "sync" + ctypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/types" types "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types" - "sync" + + "github.com/eris-ltd/eris-db/tmsp" ) // The net struct. type namereg struct { - consensusState *cm.ConsensusState - filterFactory *FilterFactory + erisdbApp *tmsp.ErisDBApp + filterFactory *FilterFactory } -func newNamereg(consensusState *cm.ConsensusState) *namereg { +func newNamereg(erisdbApp *tmsp.ErisDBApp) *namereg { ff := NewFilterFactory() @@ -44,11 +46,11 @@ func newNamereg(consensusState *cm.ConsensusState) *namereg { }, }) - return &namereg{consensusState, ff} + return &namereg{erisdbApp, ff} } func (this *namereg) Entry(key string) (*types.NameRegEntry, error) { - st := this.consensusState.GetState() // performs a copy + st := this.erisdbApp.GetState() // performs a copy entry := st.GetNameRegEntry(key) if entry == nil { return nil, fmt.Errorf("Entry %s not found", key) @@ -59,7 +61,7 @@ func (this *namereg) Entry(key string) (*types.NameRegEntry, error) { func (this *namereg) Entries(filters []*FilterData) (*ctypes.ResultListNames, error) { var blockHeight int var names []*types.NameRegEntry - state := this.consensusState.GetState() + state := this.erisdbApp.GetState() blockHeight = state.LastBlockHeight filter, err := this.filterFactory.NewFilter(filters) if err != nil { diff --git a/erisdb/pipe/net.go b/erisdb/pipe/net.go index 914b49d1f4022b8f4577502947470220615f0002..9e47337614e182fcd2d11ecc56d742e1a0e26af9 100644 --- a/erisdb/pipe/net.go +++ b/erisdb/pipe/net.go @@ -1,79 +1,50 @@ package pipe -import ( - "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p" -) +import () + +// TODO-RPC! // The net struct. type network struct { - p2pSwitch *p2p.Switch } -func newNetwork(p2pSwitch *p2p.Switch) *network { - return &network{p2pSwitch} +func newNetwork() *network { + return &network{} } //----------------------------------------------------------------------------- // Get the complete net info. func (this *network) Info() (*NetworkInfo, error) { - version := config.GetString("version") - moniker := config.GetString("moniker") - listening := this.p2pSwitch.IsListening() - listeners := []string{} - for _, listener := range this.p2pSwitch.Listeners() { - listeners = append(listeners, listener.String()) - } - peers := make([]*Peer, 0) - for _, peer := range this.p2pSwitch.Peers().List() { - p := &Peer{peer.NodeInfo, peer.IsOutbound()} - peers = append(peers, p) - } - return &NetworkInfo{ - version, - moniker, - listening, - listeners, - peers, - }, nil + return &NetworkInfo{}, nil } // Get the client version func (this *network) ClientVersion() (string, error) { - return config.GetString("version"), nil + return "not-fully-loaded-yet", nil } // Get the moniker func (this *network) Moniker() (string, error) { - return config.GetString("moniker"), nil + return "rekinom", nil } // Is the network currently listening for connections. func (this *network) Listening() (bool, error) { - return this.p2pSwitch.IsListening(), nil + return false, nil } // Is the network currently listening for connections. func (this *network) Listeners() ([]string, error) { - listeners := []string{} - for _, listener := range this.p2pSwitch.Listeners() { - listeners = append(listeners, listener.String()) - } - return listeners, nil + return []string{}, nil } // Get a list of all peers. func (this *network) Peers() ([]*Peer, error) { - peers := make([]*Peer, 0) - for _, peer := range this.p2pSwitch.Peers().List() { - p := &Peer{peer.NodeInfo, peer.IsOutbound()} - peers = append(peers, p) - } - return peers, nil + return []*Peer{}, nil } // Get a peer. TODO Need to do something about the address. func (this *network) Peer(address string) (*Peer, error) { - peer := this.p2pSwitch.Peers().Get(address) - return &Peer{peer.NodeInfo, peer.IsOutbound()}, nil + return &Peer{}, nil } diff --git a/erisdb/pipe/pipe.go b/erisdb/pipe/pipe.go index 58603661ccfd87f5a3523900c9c8bc81e676ae9c..aa9a960c17c7b03202c6377cc27d373f560320cb 100644 --- a/erisdb/pipe/pipe.go +++ b/erisdb/pipe/pipe.go @@ -3,9 +3,11 @@ package pipe import ( "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/account" - "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/node" + em "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/events" ctypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/types" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types" + + "github.com/eris-ltd/eris-db/tmsp" ) type ( @@ -79,7 +81,8 @@ type ( // Base struct for getting rpc proxy objects (node.Node has no interface). type PipeImpl struct { - tNode *node.Node + //tNode *node.Node + erisdbApp *tmsp.ErisDBApp accounts Accounts blockchain Blockchain consensus Consensus @@ -90,23 +93,28 @@ type PipeImpl struct { } // Create a new rpc pipe. -func NewPipe(tNode *node.Node) Pipe { - accounts := newAccounts(tNode.ConsensusState(), tNode.MempoolReactor()) - blockchain := newBlockchain(tNode.BlockStore()) - consensus := newConsensus(tNode.ConsensusState(), tNode.Switch()) - events := newEvents(tNode.EventSwitch()) - namereg := newNamereg(tNode.ConsensusState()) - net := newNetwork(tNode.Switch()) - txs := newTransactor(tNode.EventSwitch(), tNode.ConsensusState(), tNode.MempoolReactor(), events) +func NewPipe(erisdbApp *tmsp.ErisDBApp) Pipe { + eventSwitch := em.NewEventSwitch() + events := newEvents(eventSwitch) + + accounts := newAccounts(erisdbApp) + namereg := newNamereg(erisdbApp) + txs := newTransactor(eventSwitch, erisdbApp, events) + + // TODO: make interface to tendermint core's rpc for these + // blockchain := newBlockchain(blockStore) + // consensus := newConsensus(erisdbApp) + // net := newNetwork(erisdbApp) + return &PipeImpl{ - tNode, - accounts, - blockchain, - consensus, - events, - namereg, - net, - txs, + erisdbApp: erisdbApp, + accounts: accounts, + // blockchain, + // consensus, + events: events, + namereg: namereg, + // net, + txs: txs, } } diff --git a/erisdb/pipe/transactor.go b/erisdb/pipe/transactor.go index b8693485ee9ce8b05e8c163cc31df66b36ecec15..cbb1b5a187663be2726a305992ddad8895b3eddd 100644 --- a/erisdb/pipe/transactor.go +++ b/erisdb/pipe/transactor.go @@ -4,31 +4,30 @@ import ( "bytes" "encoding/hex" "fmt" + "sync" + "time" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/account" cmn "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common" - cs "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus" tEvents "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/events" - mempl "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/mempool" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/state" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/vm" - "sync" - "time" + + "github.com/eris-ltd/eris-db/tmsp" ) type transactor struct { - eventSwitch tEvents.Fireable - consensusState *cs.ConsensusState - mempoolReactor *mempl.MempoolReactor - eventEmitter EventEmitter - txMtx *sync.Mutex + eventSwitch tEvents.Fireable + erisdbApp *tmsp.ErisDBApp + eventEmitter EventEmitter + txMtx *sync.Mutex } -func newTransactor(eventSwitch tEvents.Fireable, consensusState *cs.ConsensusState, mempoolReactor *mempl.MempoolReactor, eventEmitter EventEmitter) *transactor { +func newTransactor(eventSwitch tEvents.Fireable, erisdbApp *tmsp.ErisDBApp, eventEmitter EventEmitter) *transactor { txs := &transactor{ eventSwitch, - consensusState, - mempoolReactor, + erisdbApp, eventEmitter, &sync.Mutex{}, } @@ -39,7 +38,7 @@ func newTransactor(eventSwitch tEvents.Fireable, consensusState *cs.ConsensusSta // Cannot be used to create new contracts func (this *transactor) Call(fromAddress, toAddress, data []byte) (*Call, error) { - st := this.consensusState.GetState() // performs a copy + st := this.erisdbApp.GetState() // performs a copy cache := state.NewBlockCache(st) outAcc := cache.GetAccount(toAddress) if outAcc == nil { @@ -74,8 +73,8 @@ func (this *transactor) CallCode(fromAddress, code, data []byte) (*Call, error) if fromAddress == nil { fromAddress = []byte{} } - st := this.consensusState.GetState() // performs a copy - cache := this.mempoolReactor.Mempool.GetCache() + st := this.erisdbApp.GetState() // performs a copy + cache := state.NewBlockCache(st) // TODO: should use mempool cache! callee := &vm.Account{Address: cmn.LeftPadWord256(fromAddress)} caller := &vm.Account{Address: cmn.LeftPadWord256(fromAddress)} txCache := state.NewTxCache(cache) @@ -97,10 +96,13 @@ func (this *transactor) CallCode(fromAddress, code, data []byte) (*Call, error) // Broadcast a transaction. func (this *transactor) BroadcastTx(tx types.Tx) (*Receipt, error) { - err := this.mempoolReactor.BroadcastTx(tx) - if err != nil { - return nil, fmt.Errorf("Error broadcasting transaction: %v", err) - } + // TODO-RPC ! + /* + err := this.mempoolReactor.BroadcastTx(tx) + if err != nil { + return nil, fmt.Errorf("Error broadcasting transaction: %v", err) + }*/ + chainId := config.GetString("chain_id") txHash := types.TxID(chainId, tx) var createsContract uint8 @@ -117,8 +119,8 @@ func (this *transactor) BroadcastTx(tx types.Tx) (*Receipt, error) { // Get all unconfirmed txs. func (this *transactor) UnconfirmedTxs() (*UnconfirmedTxs, error) { - transactions := this.mempoolReactor.Mempool.GetProposalTxs() - return &UnconfirmedTxs{transactions}, nil + // TODO-RPC + return &UnconfirmedTxs{}, nil } func (this *transactor) Transact(privKey, address, data []byte, gasLimit, fee int64) (*Receipt, error) { @@ -136,7 +138,7 @@ func (this *transactor) Transact(privKey, address, data []byte, gasLimit, fee in this.txMtx.Lock() defer this.txMtx.Unlock() pa := account.GenPrivAccountFromPrivKeyBytes(privKey) - cache := this.mempoolReactor.Mempool.GetCache() + cache := this.erisdbApp.GetState() // TODO: use mempool cache! acc := cache.GetAccount(pa.Address) var sequence int if acc == nil { @@ -216,7 +218,7 @@ func (this *transactor) TransactNameReg(privKey []byte, name, data string, amoun this.txMtx.Lock() defer this.txMtx.Unlock() pa := account.GenPrivAccountFromPrivKeyBytes(privKey) - cache := this.mempoolReactor.Mempool.GetCache() + cache := this.erisdbApp.GetState() // TODO: use mempool cache acc := cache.GetAccount(pa.Address) var sequence int if acc == nil { diff --git a/erisdb/serve.go b/erisdb/serve.go index 5727c4a402c8ad4b04c43d50f431a057e2517afc..6edf56da2ab47f0dfe227f572df92b0ca9e1d315 100644 --- a/erisdb/serve.go +++ b/erisdb/serve.go @@ -3,15 +3,26 @@ package erisdb import ( + "bytes" + "path" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/log15" . "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common" cfg "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/config" tmcfg "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/config/tendermint" + dbm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/db" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/events" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/node" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p" + sm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/state" + stypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/state/types" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/wire" + ep "github.com/eris-ltd/eris-db/erisdb/pipe" "github.com/eris-ltd/eris-db/server" - "path" + + edbapp "github.com/eris-ltd/eris-db/tmsp" + tmsp "github.com/tendermint/tmsp/server" ) const ERISDB_VERSION = "0.11.5" @@ -57,14 +68,57 @@ func ServeErisDB(workDir string) (*server.ServeProcess, error) { cfg.ApplyConfig(tmConfig) // Notify modules of new config // Set the node up. - nodeRd := make(chan struct{}) - nd := node.NewNode() - // Load the supporting objects. - pipe := ep.NewPipe(nd) + // nodeRd := make(chan struct{}) + // nd := node.NewNode() + + // Load the application state + // The app state used to be managed by tendermint node, + // but is now managed by ErisDB. + // The tendermint core only stores the blockchain (history of txs) + stateDB := dbm.GetDB("state") + state := sm.LoadState(stateDB) + 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(stypes.GenDocKey, buf.Bytes()) + if *err != nil { + Exit(Fmt("Unable to write gendoc to db: %v", err)) + } + } else { + genDocBytes := stateDB.Get(stypes.GenDocKey) + err := new(error) + wire.ReadJSONPtr(&genDoc, genDocBytes, err) + if *err != nil { + Exit(Fmt("Unable to read gendoc from db: %v", err)) + } + } + // add the chainid to the global config + config.Set("chain_id", state.ChainID) + + evsw := events.NewEventSwitch() + app := edbapp.NewErisDBApp(state, evsw) + + // Start the tmsp listener for state update commands + go func() { + // TODO config + _, err := tmsp.StartListener("tcp://0.0.0.0:46658", app) + if err != nil { + // TODO: play nice + Exit(err.Error()) + } + }() + + // Load supporting objects. + pipe := ep.NewPipe(app) codec := &TCodec{} evtSubs := NewEventSubscriptions(pipe.Events()) // The services. tmwss := NewErisDbWsService(codec, pipe) + // tmjs := NewErisDbJsonService(codec, pipe, evtSubs) // The servers. jsonServer := NewJsonRpcServer(tmjs) @@ -73,9 +127,9 @@ func ServeErisDB(workDir string) (*server.ServeProcess, error) { // Create a server process. proc := server.NewServeProcess(sConf, jsonServer, restServer, wsServer) - stopChan := proc.StopEventChannel() - go startNode(nd, nodeRd, stopChan) - <-nodeRd + //stopChan := proc.StopEventChannel() + //go startNode(nd, nodeRd, stopChan) + //<-nodeRd return proc, nil } diff --git a/tmsp/erisdb.go b/tmsp/erisdb.go new file mode 100644 index 0000000000000000000000000000000000000000..af509616ae83ff749d07a97e289c87ef7d3c682c --- /dev/null +++ b/tmsp/erisdb.go @@ -0,0 +1,137 @@ +package tmsp + +import ( + "bytes" + "sync" + + //sm "github.com/eris-ltd/eris-db/state" + // txs "github.com/eris-ltd/eris-db/txs" + + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/events" + sm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/state" + txs "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/wire" + + "github.com/tendermint/tmsp/types" +) + +//-------------------------------------------------------------------------------- +// ErisDBApp holds the current state and opens new contexts for proposed updates to the state + +type ErisDBApp struct { + mtx sync.Mutex + + state *sm.State + evsw *events.EventSwitch +} + +func (app *ErisDBApp) GetState() *sm.State { + app.mtx.Lock() + defer app.mtx.Unlock() + return app.state.Copy() +} + +func NewErisDBApp(s *sm.State, evsw *events.EventSwitch) *ErisDBApp { + return &ErisDBApp{ + state: s, + evsw: evsw, + } +} + +// Implements tmsp.Application +func (app *ErisDBApp) Open() types.AppContext { + app.mtx.Lock() + state := app.state.Copy() + app.mtx.Unlock() + return &ErisDBAppContext{ + state: state, + cache: sm.NewBlockCache(state), + evc: events.NewEventCache(app.evsw), + } +} + +//-------------------------------------------------------------------------------- +// ErisDBAppContext runs transactions, computes hashes, and handles commits/rollbacks. +// Typically two contexts (connections) are opened by the tendermint core: +// one for mempool, one for consensus. + +type ErisDBAppContext struct { + app *ErisDBApp + + state *sm.State + cache *sm.BlockCache + + evc *events.EventCache +} + +func (appC *ErisDBAppContext) Echo(message string) string { + return message +} + +func (appC *ErisDBAppContext) Info() []string { + return []string{"ErisDB"} +} + +func (appC *ErisDBAppContext) SetOption(key string, value string) types.RetCode { + return 0 +} + +func (appC ErisDBAppContext) AppendTx(txBytes []byte) ([]types.Event, types.RetCode) { + var n int64 + var err error + tx := new(txs.Tx) + buf := bytes.NewBuffer(txBytes) + wire.ReadBinaryPtr(tx, buf, &n, &err) + if err != nil { + // TODO: handle error + return nil, types.RetCodeEncodingError + } + + err = sm.ExecTx(appC.cache, *tx, true, appC.evc) + if err != nil { + // TODO: handle error + return nil, types.RetCodeInternalError // ?! + } + + return nil, types.RetCodeOK +} + +func (appC *ErisDBAppContext) GetHash() ([]byte, types.RetCode) { + appC.cache.Sync() + return appC.state.Hash(), types.RetCodeOK +} + +func (appC *ErisDBAppContext) Commit() types.RetCode { + // save state to disk + appC.state.Save() + + // flush events to listeners + appC.evc.Flush() + + // update underlying app state for new tmsp connections + appC.app.mtx.Lock() + appC.app.state = appC.state + appC.app.mtx.Unlock() + return 0 +} + +func (appC *ErisDBAppContext) Rollback() types.RetCode { + appC.app.mtx.Lock() + appC.state = appC.app.state + appC.app.mtx.Unlock() + + appC.cache = sm.NewBlockCache(appC.state) + return 0 +} + +func (appC *ErisDBAppContext) AddListener(key string) types.RetCode { + return 0 +} + +func (appC *ErisDBAppContext) RemListener(key string) types.RetCode { + return 0 +} + +func (appC *ErisDBAppContext) Close() error { + return nil +}