From d36fe323c9b04a4b43b4c3c3e051bc76e46b9c3e Mon Sep 17 00:00:00 2001
From: androlo <andreas@erisindustries.com>
Date: Tue, 21 Jul 2015 16:29:29 +0200
Subject: [PATCH] namereg, bump to 0.11.0

---
 erisdb/methods.go                  |  57 +++++++-
 erisdb/params.go                   |  22 +++
 erisdb/pipe/accounts.go            |   2 +-
 erisdb/pipe/namereg.go             | 218 +++++++++++++++++++++++++++++
 erisdb/pipe/pipe.go                |  15 ++
 erisdb/pipe/transactor.go          |  30 +++-
 erisdb/restServer.go               |  50 +++++++
 erisdb/serve.go                    |   2 +-
 test/mock/mock_web_api_test.go     |  29 ++++
 test/mock/pipe.go                  |  27 ++++
 test/testdata/testdata/testdata.go |  71 +++++++++-
 11 files changed, 510 insertions(+), 13 deletions(-)
 create mode 100644 erisdb/pipe/namereg.go

diff --git a/erisdb/methods.go b/erisdb/methods.go
index 634869a4..be9e49f7 100644
--- a/erisdb/methods.go
+++ b/erisdb/methods.go
@@ -42,9 +42,12 @@ const (
 	GET_UNCONFIRMED_TXS       = SERVICE_NAME + ".getUnconfirmedTxs"
 	SIGN_TX                   = SERVICE_NAME + ".signTx"
 	TRANSACT                  = SERVICE_NAME + ".transact"
+	TRANSACT_NAMEREG          = SERVICE_NAME + ".transactNameReg"
 	EVENT_SUBSCRIBE           = SERVICE_NAME + ".eventSubscribe" // Events
 	EVENT_UNSUBSCRIBE         = SERVICE_NAME + ".eventUnsubscribe"
 	EVENT_POLL                = SERVICE_NAME + ".eventPoll"
+	GET_NAMEREG_ENTRY         = SERVICE_NAME + ".getNameRegEntry" // Namereg
+	GET_NAMEREG_ENTRIES       = SERVICE_NAME + ".getNameRegEntries"
 )
 
 // The rpc method handlers.
@@ -60,7 +63,7 @@ type RequestHandlerFunc func(*rpc.RPCRequest, interface{}) (interface{}, int, er
 func (this *ErisDbMethods) getMethods() map[string]RequestHandlerFunc {
 	dhMap := make(map[string]RequestHandlerFunc)
 	// Accounts
-	dhMap[GET_ACCOUNTS] = this.AccountList
+	dhMap[GET_ACCOUNTS] = this.Accounts
 	dhMap[GET_ACCOUNT] = this.Account
 	dhMap[GET_STORAGE] = this.AccountStorage
 	dhMap[GET_STORAGE_AT] = this.AccountStorageAt
@@ -92,6 +95,10 @@ func (this *ErisDbMethods) getMethods() map[string]RequestHandlerFunc {
 	dhMap[GET_UNCONFIRMED_TXS] = this.UnconfirmedTxs
 	dhMap[SIGN_TX] = this.SignTx
 	dhMap[TRANSACT] = this.Transact
+	dhMap[TRANSACT_NAMEREG] = this.TransactNameReg
+	// Namereg
+	dhMap[GET_NAMEREG_ENTRY] = this.NameRegEntry
+	dhMap[GET_NAMEREG_ENTRIES] = this.NameRegEntries
 
 	return dhMap
 }
@@ -140,7 +147,7 @@ func (this *ErisDbMethods) Account(request *rpc.RPCRequest, requester interface{
 	return account, 0, nil
 }
 
-func (this *ErisDbMethods) AccountList(request *rpc.RPCRequest, requester interface{}) (interface{}, int, error) {
+func (this *ErisDbMethods) Accounts(request *rpc.RPCRequest, requester interface{}) (interface{}, int, error) {
 	param := &AccountsParam{}
 	fmt.Printf("ACCOUNT LIST REQUEST: %v\n", request)
 	err := this.codec.DecodeBytes(param, request.Params)
@@ -394,6 +401,19 @@ func (this *ErisDbMethods) Transact(request *rpc.RPCRequest, requester interface
 	return receipt, 0, nil
 }
 
+func (this *ErisDbMethods) TransactNameReg(request *rpc.RPCRequest, requester interface{}) (interface{}, int, error) {
+	param := &TransactNameRegParam{}
+	err := this.codec.DecodeBytes(param, request.Params)
+	if err != nil {
+		return nil, rpc.INVALID_PARAMS, err
+	}
+	receipt, errC := this.pipe.Transactor().TransactNameReg(param.PrivKey, param.Name, param.Data, param.Amount, param.Fee)
+	if errC != nil {
+		return nil, rpc.INTERNAL_ERROR, errC
+	}
+	return receipt, 0, nil
+}
+
 func (this *ErisDbMethods) UnconfirmedTxs(request *rpc.RPCRequest, requester interface{}) (interface{}, int, error) {
 	txs, errC := this.pipe.Transactor().UnconfirmedTxs()
 	if errC != nil {
@@ -417,6 +437,39 @@ func (this *ErisDbMethods) SignTx(request *rpc.RPCRequest, requester interface{}
 	return txRet, 0, nil
 }
 
+
+// *************************************** Name Registry ***************************************
+
+func (this *ErisDbMethods) NameRegEntry(request *rpc.RPCRequest, requester interface{}) (interface{}, int, error) {
+	param := &NameRegEntryParam{}
+	err := this.codec.DecodeBytes(param, request.Params)
+	if err != nil {
+		return nil, rpc.INVALID_PARAMS, err
+	}
+	name := param.Name
+	// TODO is address check?
+	entry, errC := this.pipe.NameReg().Entry(name)
+	if errC != nil {
+		return nil, rpc.INTERNAL_ERROR, errC
+	}
+	return entry, 0, nil
+}
+
+func (this *ErisDbMethods) NameRegEntries(request *rpc.RPCRequest, requester interface{}) (interface{}, int, error) {
+	param := &FilterListParam{}
+	fmt.Printf("ACCOUNT LIST REQUEST: %v\n", request)
+	err := this.codec.DecodeBytes(param, request.Params)
+	if err != nil {
+		return nil, rpc.INVALID_PARAMS, err
+	}
+	fmt.Printf("PARAMS: %v\n", param)
+	list, errC := this.pipe.NameReg().Entries(param.Filters)
+	if errC != nil {
+		return nil, rpc.INTERNAL_ERROR, errC
+	}
+	return list, 0, nil
+}
+
 // **************************************************************************************
 
 func generateSubId() (string, error) {
diff --git a/erisdb/params.go b/erisdb/params.go
index a1b919b9..785e716d 100644
--- a/erisdb/params.go
+++ b/erisdb/params.go
@@ -15,9 +15,15 @@ type (
 	}
 
 	// Used to send an address
+	// TODO deprecate in favor of 'FilterListParam'
 	AccountsParam struct {
 		Filters []*pipe.FilterData `json:"filters"`
 	}
+	
+	// Used to send an address
+	FilterListParam struct {
+		Filters []*pipe.FilterData `json:"filters"`
+	}
 
 	PrivKeyParam struct {
 		PrivKey []byte `json:"priv_key"`
@@ -35,6 +41,7 @@ type (
 	}
 
 	// Get a series of blocks
+	// TODO deprecate in favor of 'FilterListParam'
 	BlocksParam struct {
 		Filters []*pipe.FilterData `json:"filters"`
 	}
@@ -80,4 +87,19 @@ type (
 		Fee      int64  `json:"fee"`
 		GasLimit int64  `json:"gas_limit"`
 	}
+	
+	NameRegEntryParam struct {
+		Name string `json:"name"`
+	}
+
+	// Used when sending a namereg transaction to be created and signed on the server
+	// (using the private key). This only uses the standard key type for now.
+	TransactNameRegParam struct {
+		PrivKey []byte `json:"priv_key"`
+		Name    string `json:"name"`
+		Data    string `json:"data"`
+		Fee     int64  `json:"fee"`
+		Amount  int64  `json:"amount"`
+	}
+	
 )
diff --git a/erisdb/pipe/accounts.go b/erisdb/pipe/accounts.go
index 3da94e93..efd9f2f8 100644
--- a/erisdb/pipe/accounts.go
+++ b/erisdb/pipe/accounts.go
@@ -200,4 +200,4 @@ func (this *AccountBalanceFilter) Match(v interface{}) bool {
 		return false
 	}
 	return this.match(int64(acc.Balance), this.value)
-}
+}
\ No newline at end of file
diff --git a/erisdb/pipe/namereg.go b/erisdb/pipe/namereg.go
new file mode 100644
index 00000000..3a820f0f
--- /dev/null
+++ b/erisdb/pipe/namereg.go
@@ -0,0 +1,218 @@
+package pipe
+
+import (
+	"bytes"
+	"encoding/hex"
+	"fmt"
+	cm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/consensus"
+	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"
+)
+
+// The net struct.
+type namereg struct {
+	consensusState *cm.ConsensusState
+	filterFactory  *FilterFactory
+}
+
+func newNamereg(consensusState *cm.ConsensusState) *namereg {
+	
+	ff := NewFilterFactory()
+
+	ff.RegisterFilterPool("name", &sync.Pool{
+		New: func() interface{} {
+			return &NameRegNameFilter{}
+		},
+	})
+
+	ff.RegisterFilterPool("owner", &sync.Pool{
+		New: func() interface{} {
+			return &NameRegOwnerFilter{}
+		},
+	})
+
+	ff.RegisterFilterPool("data", &sync.Pool{
+		New: func() interface{} {
+			return &NameRegDataFilter{}
+		},
+	})
+
+	ff.RegisterFilterPool("expires", &sync.Pool{
+		New: func() interface{} {
+			return &NameRegExpiresFilter{}
+		},
+	})
+
+	return &namereg{consensusState, ff}
+}
+
+func (this *namereg) Entry(key string) (*types.NameRegEntry, error) {
+	st := this.consensusState.GetState() // performs a copy
+	entry := st.GetNameRegEntry(key)
+	if entry == nil {
+		return nil, fmt.Errorf("Entry %s not found", key)
+	}
+	return entry, nil
+}
+
+func (this *namereg) Entries(filters []*FilterData) (*ctypes.ResponseListNames, error) {
+	var blockHeight int
+	var names []*types.NameRegEntry
+	state := this.consensusState.GetState()
+	blockHeight = state.LastBlockHeight
+	filter, err := this.filterFactory.NewFilter(filters)
+	if err != nil {
+		return nil, fmt.Errorf("Error in query: " + err.Error())
+	}
+	state.GetNames().Iterate(func(key interface{}, value interface{}) bool {
+		nre := value.(*types.NameRegEntry)
+		if filter.Match(nre){
+			names = append(names, nre)
+		}
+		return false
+	})
+	return &ctypes.ResponseListNames{blockHeight, names}, nil
+}
+
+// Filter for namereg name. This should not be used to get individual entries by name.
+// Ops: == or !=
+type NameRegNameFilter struct {
+	op    string
+	value string
+	match func(string, string) bool
+}
+
+func (this *NameRegNameFilter) Configure(fd *FilterData) error {
+	op := fd.Op
+	val := fd.Value
+
+	if op == "==" {
+		this.match = func(a, b string) bool {
+			return a == b
+		}
+	} else if op == "!=" {
+		this.match = func(a, b string) bool {
+			return a != b
+		}
+	} else {
+		return fmt.Errorf("Op: " + this.op + " is not supported for 'name' filtering")
+	}
+	this.op = op
+	this.value = val
+	return nil
+}
+
+func (this *NameRegNameFilter) Match(v interface{}) bool {
+	nre, ok := v.(*types.NameRegEntry)
+	if !ok {
+		return false
+	}
+	return this.match(nre.Name, this.value)
+}
+
+// Filter for owner.
+// Ops: == or !=
+type NameRegOwnerFilter struct {
+	op    string
+	value []byte
+	match func([]byte, []byte) bool
+}
+
+func (this *NameRegOwnerFilter) Configure(fd *FilterData) error {
+	op := fd.Op
+	val, err := hex.DecodeString(fd.Value)
+
+	if err != nil {
+		return fmt.Errorf("Wrong value type.")
+	}
+	if op == "==" {
+		this.match = func(a, b []byte) bool {
+			return bytes.Equal(a, b)
+		}
+	} else if op == "!=" {
+		this.match = func(a, b []byte) bool {
+			return !bytes.Equal(a, b)
+		}
+	} else {
+		return fmt.Errorf("Op: " + this.op + " is not supported for 'owner' filtering")
+	}
+	this.op = op
+	this.value = val
+	return nil
+}
+
+func (this *NameRegOwnerFilter) Match(v interface{}) bool {
+	nre, ok := v.(*types.NameRegEntry)
+	if !ok {
+		return false
+	}
+	return this.match(nre.Owner, this.value)
+}
+
+// Filter for namereg data. Useful for example if you store an ipfs hash and know the hash but need the key.
+// Ops: == or !=
+type NameRegDataFilter struct {
+	op    string
+	value string
+	match func(string, string) bool
+}
+
+func (this *NameRegDataFilter) Configure(fd *FilterData) error {
+	op := fd.Op
+	val := fd.Value
+
+	if op == "==" {
+		this.match = func(a, b string) bool {
+			return a == b
+		}
+	} else if op == "!=" {
+		this.match = func(a, b string) bool {
+			return a != b
+		}
+	} else {
+		return fmt.Errorf("Op: " + this.op + " is not supported for 'data' filtering")
+	}
+	this.op = op
+	this.value = val
+	return nil
+}
+
+func (this *NameRegDataFilter) Match(v interface{}) bool {
+	nre, ok := v.(*types.NameRegEntry)
+	if !ok {
+		return false
+	}
+	return this.match(nre.Data, this.value)
+}
+
+// Filter for expires.
+// Ops: All
+type NameRegExpiresFilter struct {
+	op    string
+	value int64
+	match func(int64, int64) bool
+}
+
+func (this *NameRegExpiresFilter) Configure(fd *FilterData) error {
+	val, err := ParseNumberValue(fd.Value)
+	if err != nil {
+		return err
+	}
+	match, err2 := GetRangeFilter(fd.Op, "expires")
+	if err2 != nil {
+		return err2
+	}
+	this.match = match
+	this.op = fd.Op
+	this.value = val
+	return nil
+}
+
+func (this *NameRegExpiresFilter) Match(v interface{}) bool {
+	nre, ok := v.(*types.NameRegEntry)
+	if !ok {
+		return false
+	}
+	return this.match(int64(nre.Expires), this.value)
+}
diff --git a/erisdb/pipe/pipe.go b/erisdb/pipe/pipe.go
index 59069488..b4c4aa19 100644
--- a/erisdb/pipe/pipe.go
+++ b/erisdb/pipe/pipe.go
@@ -4,6 +4,7 @@ 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"
+	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"
 )
 
@@ -15,6 +16,7 @@ type (
 		Blockchain() Blockchain
 		Consensus() Consensus
 		Events() EventEmitter
+		NameReg() NameReg
 		Net() Net
 		Transactor() Transactor
 	}
@@ -47,6 +49,11 @@ type (
 		Subscribe(subId, event string, callback func(interface{})) (bool, error)
 		Unsubscribe(subId string) (bool, error)
 	}
+	
+	NameReg interface {
+		 Entry(key string) (*types.NameRegEntry, error)
+		 Entries([]*FilterData) (*ctypes.ResponseListNames, error)
+	}
 
 	Net interface {
 		Info() (*NetworkInfo, error)
@@ -63,6 +70,7 @@ type (
 		CallCode(code, data []byte) (*Call, error)
 		BroadcastTx(tx types.Tx) (*Receipt, error)
 		Transact(privKey, address, data []byte, gasLimit, fee int64) (*Receipt, error)
+		TransactNameReg(privKey []byte, name, data string, amount, fee int64) (*Receipt, error)
 		UnconfirmedTxs() (*UnconfirmedTxs, error)
 		SignTx(tx types.Tx, privAccounts []*account.PrivAccount) (types.Tx, error)
 	}
@@ -75,6 +83,7 @@ type PipeImpl struct {
 	blockchain Blockchain
 	consensus  Consensus
 	events     EventEmitter
+	namereg    NameReg
 	net        Net
 	txs        Transactor
 }
@@ -85,6 +94,7 @@ func NewPipe(tNode *node.Node) Pipe {
 	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)
 	return &PipeImpl{
@@ -93,6 +103,7 @@ func NewPipe(tNode *node.Node) Pipe {
 		blockchain,
 		consensus,
 		events,
+		namereg,
 		net,
 		txs,
 	}
@@ -114,6 +125,10 @@ func (this *PipeImpl) Events() EventEmitter {
 	return this.events
 }
 
+func (this *PipeImpl) NameReg() NameReg {
+	return this.namereg
+}
+
 func (this *PipeImpl) Net() Net {
 	return this.net
 }
diff --git a/erisdb/pipe/transactor.go b/erisdb/pipe/transactor.go
index 1a1e2b50..2a08f653 100644
--- a/erisdb/pipe/transactor.go
+++ b/erisdb/pipe/transactor.go
@@ -118,7 +118,6 @@ func (this *transactor) UnconfirmedTxs() (*UnconfirmedTxs, error) {
 }
 
 func (this *transactor) Transact(privKey, address, data []byte, gasLimit, fee int64) (*Receipt, error) {
-	fmt.Printf("ADDRESS: %v\n", address)
 	var addr []byte
 	if len(address) == 0 {
 		addr = nil
@@ -140,7 +139,6 @@ func (this *transactor) Transact(privKey, address, data []byte, gasLimit, fee in
 	} else {
 		sequence = acc.Sequence + 1
 	}
-	fmt.Printf("NONCE: %d\n", sequence)
 	txInput := &types.TxInput{
 		Address:  pa.Address,
 		Amount:   1,
@@ -162,6 +160,30 @@ func (this *transactor) Transact(privKey, address, data []byte, gasLimit, fee in
 	return this.BroadcastTx(txS)
 }
 
+func (this *transactor) TransactNameReg(privKey []byte, name, data string, amount, fee int64) (*Receipt, error) {
+	
+	if len(privKey) != 64 {
+		return nil, fmt.Errorf("Private key is not of the right length: %d\n", len(privKey))
+	}
+
+	pa := account.GenPrivAccountFromPrivKeyBytes(privKey)
+	cache := this.mempoolReactor.Mempool.GetCache()
+	acc := cache.GetAccount(pa.Address)
+	var sequence int
+	if acc == nil {
+		sequence = 1
+	} else {
+		sequence = acc.Sequence + 1
+	}
+	tx := types.NewNameTxWithNonce(pa.PubKey, name, data, amount, fee, sequence)
+	// Got ourselves a tx.
+	txS, errS := this.SignTx(tx, []*account.PrivAccount{pa})
+	if errS != nil {
+		return nil, errS
+	}
+	return this.BroadcastTx(txS)
+}
+
 // Sign a transaction
 func (this *transactor) SignTx(tx types.Tx, privAccounts []*account.PrivAccount) (types.Tx, error) {
 	// more checks?
@@ -173,6 +195,10 @@ func (this *transactor) SignTx(tx types.Tx, privAccounts []*account.PrivAccount)
 	}
 	chainId := config.GetString("chain_id")
 	switch tx.(type) {
+	case *types.NameTx:
+		nameTx := tx.(*types.NameTx)
+		nameTx.Input.PubKey = privAccounts[0].PubKey
+		nameTx.Input.Signature = privAccounts[0].Sign(config.GetString("chain_id"), nameTx)
 	case *types.SendTx:
 		sendTx := tx.(*types.SendTx)
 		for i, input := range sendTx.Inputs {
diff --git a/erisdb/restServer.go b/erisdb/restServer.go
index 2cf2432d..df933579 100644
--- a/erisdb/restServer.go
+++ b/erisdb/restServer.go
@@ -50,6 +50,9 @@ func (this *RestServer) Start(config *server.ServerConfig, router *gin.Engine) {
 	router.POST("/event_subs", this.handleEventSubscribe)
 	router.GET("/event_subs/:id", this.handleEventPoll)
 	router.DELETE("/event_subs/:id", this.handleEventUnsubscribe)
+	// NameReg
+	router.GET("/namereg", parseQuery, this.handleNameRegEntries)
+	router.GET("/namereg/:key", nameParam, this.handleNameRegEntry)
 	// Network
 	router.GET("/network", this.handleNetworkInfo)
 	router.GET("/network/client_version", this.handleClientVersion)
@@ -67,6 +70,7 @@ func (this *RestServer) Start(config *server.ServerConfig, router *gin.Engine) {
 	// Unsafe
 	router.GET("/unsafe/pa_generator", this.handleGenPrivAcc)
 	router.POST("/unsafe/txpool", this.handleTransact)
+	router.POST("/unsafe/namereg/txpool", this.handleTransactNameReg)
 	router.POST("/unsafe/tx_signer", this.handleSignTx)
 	this.running = true
 }
@@ -273,6 +277,32 @@ func (this *RestServer) handleEventUnsubscribe(c *gin.Context) {
 	this.codec.Encode(&ep.EventUnsub{true}, c.Writer)
 }
 
+// ********************************* NameReg *********************************
+
+func (this *RestServer) handleNameRegEntries(c *gin.Context) {
+	var filters []*ep.FilterData
+	fs, exists := c.Get("filters")
+	if exists {
+		filters = fs.([]*ep.FilterData)
+	}
+	entries, err := this.pipe.NameReg().Entries(filters)
+	if err != nil {
+		c.AbortWithError(500, err)
+	}
+	c.Writer.WriteHeader(200)
+	this.codec.Encode(entries, c.Writer)
+}
+
+func (this *RestServer) handleNameRegEntry(c *gin.Context) {
+	name := c.MustGet("name").(string)
+	entry, err := this.pipe.NameReg().Entry(name)
+	if err != nil {
+		c.AbortWithError(500, err)
+	}
+	c.Writer.WriteHeader(200)
+	this.codec.Encode(entry, c.Writer)
+}
+
 // ********************************* Network *********************************
 
 func (this *RestServer) handleNetworkInfo(c *gin.Context) {
@@ -407,6 +437,20 @@ func (this *RestServer) handleTransact(c *gin.Context) {
 	this.codec.Encode(receipt, c.Writer)
 }
 
+func (this *RestServer) handleTransactNameReg(c *gin.Context) {
+	param := &TransactNameRegParam{}
+	errD := this.codec.Decode(param, c.Request.Body)
+	if errD != nil {
+		c.AbortWithError(500, errD)
+	}
+	receipt, err := this.pipe.Transactor().TransactNameReg(param.PrivKey, param.Name, param.Data, param.Amount, param.Fee)
+	if err != nil {
+		c.AbortWithError(500, err)
+	}
+	c.Writer.WriteHeader(200)
+	this.codec.Encode(receipt, c.Writer)
+}
+
 func (this *RestServer) handleSignTx(c *gin.Context) {
 	param := &SignTxParam{}
 	errD := this.codec.Decode(param, c.Request.Body)
@@ -433,6 +477,12 @@ func addressParam(c *gin.Context) {
 	c.Next()
 }
 
+func nameParam(c *gin.Context) {
+	name := c.Param("key")
+	c.Set("name", name)
+	c.Next()
+}
+
 func keyParam(c *gin.Context) {
 	key := c.Param("key")
 	bts, err := hex.DecodeString(key)
diff --git a/erisdb/serve.go b/erisdb/serve.go
index 7ddc3826..462db427 100644
--- a/erisdb/serve.go
+++ b/erisdb/serve.go
@@ -14,7 +14,7 @@ import (
 	"path"
 )
 
-const ERISDB_VERSION = "0.10.4"
+const ERISDB_VERSION = "0.11.0"
 const TENDERMINT_VERSION = "0.5.0"
 
 var log = log15.New("module", "eris/erisdb_server")
diff --git a/test/mock/mock_web_api_test.go b/test/mock/mock_web_api_test.go
index eb8d55ae..e48be250 100644
--- a/test/mock/mock_web_api_test.go
+++ b/test/mock/mock_web_api_test.go
@@ -9,6 +9,8 @@ import (
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/stretchr/testify/suite"
 	"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/account"
+	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types"
+	ctypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/types"
 	edb "github.com/eris-ltd/eris-db/erisdb"
 	ep "github.com/eris-ltd/eris-db/erisdb/pipe"
 	"github.com/eris-ltd/eris-db/rpc"
@@ -166,6 +168,25 @@ func (this *MockSuite) TestGetValidators() {
 	this.Equal(ret, this.testData.GetValidators.Output)
 }
 
+
+// ********************************************* NameReg *********************************************
+
+func (this *MockSuite) TestGetNameRegEntry() {
+	resp := this.get("/namereg/" + this.testData.GetNameRegEntry.Input.Name)
+	ret := &types.NameRegEntry{}
+	errD := this.codec.Decode(ret, resp.Body)
+	this.NoError(errD)
+	this.Equal(ret, this.testData.GetNameRegEntry.Output)
+}
+
+func (this *MockSuite) TestGetNameRegEntries() {
+	resp := this.get("/namereg")
+	ret := &ctypes.ResponseListNames{}
+	errD := this.codec.Decode(ret, resp.Body)
+	this.NoError(errD)
+	this.Equal(ret, this.testData.GetNameRegEntries.Output)
+}
+
 // ********************************************* Network *********************************************
 
 func (this *MockSuite) TestGetNetworkInfo() {
@@ -245,6 +266,14 @@ func (this *MockSuite) TestTransact() {
 	this.Equal(ret, this.testData.Transact.Output)
 }
 
+func (this *MockSuite) TestTransactNameReg() {
+	resp := this.postJson("/unsafe/namereg/txpool", this.testData.TransactNameReg.Input)
+	ret := &ep.Receipt{}
+	errD := this.codec.Decode(ret, resp.Body)
+	this.NoError(errD)
+	this.Equal(ret, this.testData.TransactNameReg.Output)
+}
+
 func (this *MockSuite) TestGetUnconfirmedTxs() {
 	resp := this.get("/txpool")
 	ret := &ep.UnconfirmedTxs{}
diff --git a/test/mock/pipe.go b/test/mock/pipe.go
index 9ba2fd54..16ab4a75 100644
--- a/test/mock/pipe.go
+++ b/test/mock/pipe.go
@@ -3,6 +3,7 @@ package mock
 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/types"
+	ctypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/rpc/core/types"
 	ep "github.com/eris-ltd/eris-db/erisdb/pipe"
 	td "github.com/eris-ltd/eris-db/test/testdata/testdata"
 )
@@ -14,6 +15,7 @@ type MockPipe struct {
 	blockchain ep.Blockchain
 	consensus  ep.Consensus
 	events     ep.EventEmitter
+	namereg    ep.NameReg
 	net        ep.Net
 	transactor ep.Transactor
 }
@@ -24,6 +26,7 @@ func NewMockPipe(td *td.TestData) ep.Pipe {
 	blockchain := &blockchain{td}
 	consensus := &consensus{td}
 	events := &events{td}
+	namereg := &namereg{td}
 	net := &net{td}
 	transactor := &transactor{td}
 	return &MockPipe{
@@ -32,6 +35,7 @@ func NewMockPipe(td *td.TestData) ep.Pipe {
 		blockchain,
 		consensus,
 		events,
+		namereg,
 		net,
 		transactor,
 	}
@@ -58,6 +62,11 @@ func (this *MockPipe) Events() ep.EventEmitter {
 	return this.events
 }
 
+func (this *MockPipe) NameReg() ep.NameReg {
+	return this.namereg
+}
+
+
 func (this *MockPipe) Net() ep.Net {
 	return this.net
 }
@@ -156,6 +165,20 @@ func (this *events) Unsubscribe(subId string) (bool, error) {
 	return true, nil
 }
 
+
+// NameReg
+type namereg struct {
+	testData *td.TestData
+}
+
+func (this *namereg) Entry(key string) (*types.NameRegEntry, error) {
+	return this.testData.GetNameRegEntry.Output, nil
+}
+
+func (this *namereg) Entries(filters []*ep.FilterData) (*ctypes.ResponseListNames, error) {
+	return this.testData.GetNameRegEntries.Output, nil
+}
+
 // Net
 type net struct {
 	testData *td.TestData
@@ -218,6 +241,10 @@ func (this *transactor) Transact(privKey, address, data []byte, gasLimit, fee in
 	return this.testData.Transact.Output, nil
 }
 
+func (this *transactor) TransactNameReg(privKey []byte, name, data string, amount, fee int64) (*ep.Receipt, error) {
+	return this.testData.TransactNameReg.Output, nil
+}
+
 func (this *transactor) SignTx(tx types.Tx, privAccounts []*account.PrivAccount) (types.Tx, error) {
 	return nil, nil
 }
diff --git a/test/testdata/testdata/testdata.go b/test/testdata/testdata/testdata.go
index 0f89665f..03c43365 100644
--- a/test/testdata/testdata/testdata.go
+++ b/test/testdata/testdata/testdata.go
@@ -2,6 +2,7 @@ package testdata
 
 import (
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/account"
+	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/state"
 	"github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types"
 	edb "github.com/eris-ltd/eris-db/erisdb"
@@ -466,6 +467,44 @@ var testDataJson = `{
         }
       ]
     }
+  },
+  "TransactNameReg": {
+    "input": {
+      "priv_key": "6B72D45EB65F619F11CE580C8CAED9E0BADC774E9C9C334687A65DCBAD2C4151CB3688B7561D488A2A4834E1AEE9398BEF94844D8BDBBCA980C11E3654A45906",
+      "name": "testKey",
+      "data": "testValue",
+      "amount": 10000,
+      "fee": 0
+    },
+    "output": {
+      "tx_hash": "98B0D5162C7CB86FF94BE2C00469107B7CA51CF3",
+      "creates_contract": 0,
+      "contract_addr": ""
+    }
+  },
+  "GetNameRegEntry": {
+    "input": {
+      "name": "testKey"
+    },
+    "output": {
+      "name": "testKey",
+      "owner": "37236DF251AB70022B1DA351F08A20FB52443E37",
+      "data": "testData",
+      "expires": 250 }
+  },
+  "GetNameRegEntries": {
+    "input": {
+      "filters": []
+    },
+    "output": {
+      "block_height": 1,
+      "names":[ {
+        "name": "testKey",
+        "owner": "37236DF251AB70022B1DA351F08A20FB52443E37",
+        "data": "testData",
+        "expires": 250
+      } ]
+    }
   }
 }`
 
@@ -602,6 +641,21 @@ type (
 		Output *ep.EventUnsub  `json:"output"`
 	}
 
+	TransactNameRegData struct {
+		Input  *edb.TransactNameRegParam `json:"input"`
+		Output *ep.Receipt               `json:"output"`
+	}
+
+	GetNameRegEntryData struct {
+		Input  *edb.NameRegEntryParam `json:"input"`
+		Output *types.NameRegEntry    `json:"output"`
+	}
+
+	GetNameRegEntriesData struct {
+		Input  *edb.FilterListParam      `json:"input"`
+		Output *ctypes.ResponseListNames `json:"output"`
+	}
+
 	/*
 		EventPollData struct {
 			Input  *edb.SubIdParam  `json:"input"`
@@ -631,14 +685,17 @@ type (
 		IsListening          *IsListeningData
 		GetListeners         *GetListenersData
 		GetPeers             *GetPeersData
+		Transact             *TransactData
+		TransactCreate       *TransactCreateData
+		TransactNameReg      *TransactNameRegData
+		GetUnconfirmedTxs    *GetUnconfirmedTxsData
+		CallCode             *CallCodeData
+		Call                 *CallData
+		EventSubscribe       *EventSubscribeData
+		EventUnsubscribe     *EventUnsubscribeData
+		GetNameRegEntry      *GetNameRegEntryData
+		GetNameRegEntries    *GetNameRegEntriesData
 		// GetPeer              *GetPeerData
-		Transact          *TransactData
-		TransactCreate    *TransactCreateData
-		GetUnconfirmedTxs *GetUnconfirmedTxsData
-		CallCode          *CallCodeData
-		Call              *CallData
-		EventSubscribe    *EventSubscribeData
-		EventUnsubscribe  *EventUnsubscribeData
 		// EventPoll            *EventPollData
 	}
 )
-- 
GitLab