diff --git a/cmd/serve.go b/cmd/serve.go index 1555c6480..2717913fd 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -25,7 +25,7 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" - "github.com/tendermint/go-keys/proxy" + "github.com/tendermint/go-keys/server" ) // serveCmd represents the serve command @@ -36,7 +36,7 @@ var serveCmd = &cobra.Command{ private keys much more in depth than the cli can perform. In particular, this will allow you to sign transactions with the private keys in the store.`, - RunE: server, + RunE: serveHTTP, } func init() { @@ -46,7 +46,7 @@ func init() { serveCmd.Flags().StringP("type", "t", "ed25519", "Default key type (ed25519|secp256k1)") } -func server(cmd *cobra.Command, args []string) error { +func serveHTTP(cmd *cobra.Command, args []string) error { var l net.Listener var err error socket := viper.GetString("socket") @@ -64,7 +64,7 @@ func server(cmd *cobra.Command, args []string) error { } router := mux.NewRouter() - ks := proxy.NewKeyServer(manager, viper.GetString("type")) + ks := server.New(manager, viper.GetString("type")) ks.Register(router) // only set cors for tcp listener diff --git a/proxy/README.md b/proxy/README.md deleted file mode 100644 index 614110b7f..000000000 --- a/proxy/README.md +++ /dev/null @@ -1,65 +0,0 @@ -# Proxy Server - -This package provides all the functionality for a local proxy http server, and ties together functionality from all the other packages to acheive this aim. Simply configure this server with your application-specific settings via a main script and you are good to go. - -This server should run on the client's machine, and can accept a trusted connection from localhost (via tcp or unix socket). It provides a simple json rest API and handles all the binary wrangling and cryptographic proofs under the hood. Thus, you can host a local webapp (via electron?) and connect to this proxy, perform simple queries and posts and behind the scenes take advantage of the *awesome power* of the tendermint blockchain. - -If you are writing native code, you can use this as well, or you can look for bindings to embed this functionality directly as a library in your codebase. -**(coming soon)** - -## API - -The API has various sections based on functionality. The major portions are key management, signing and posting transactions, and querying and proving data. - -### Key Management - -We expose a number of methods for safely managing your keychain. They are typically bound under `/keys`, but could be placed in another location by the app. - -* `POST /keys/` - provide a name and passphrase and create a brand new key -* `GET /keys/` - get a list of all available key names, along with their public key and address -* `GET /keys/{name}` - get public key and address for this named key - -Later expose: - -* `PUT /keys/{name}` - update the passphrase for the given key. requires you to correctly provide the current passphrase, as well as a new one. -* `DELETE /keys/{name}` - permanently delete this private key. requires you to correctly provide the current passphrase -* export and import functionality - -### Transactions - -You want to post your transaction. Great. Your application must provide logic to transform json into a `Signable` go struct. Then we handle the rest, signing it with a keypair of your choosing, posting it to tendermint core, and returning you confirmation when it was committed. - -* `POST /txs/` - provide name, passphrase and application-specific data to post to tendermint - - -### Proving Data - -We sent some money to our friend, now we want to check his balance. No, not just look at it, but really check it, verify all those cryptographic proofs that some node is not lying and it really, truly is in his account. - -Thankfully, we have the technology and can do all the checks in the proxy, it might just take a second or two for us to get all those block headers. - -However, this still just leaves us with a bunch of binary blobs from the server, so to make this whole process less painless, you should provide some application-specific logic to parse this binary data from the blockchain, so we can present it as json over the interface. - -* `GET /query/{path}/{data}` - will quickly query the data under the given (hex-encoded) key. `path` is `key` to query by merkle key, but your application could provide other prefixes, to differentiate by types (eg. `account`, `votes`, `escrow`). The returned data is parsed into json and displayed. -* `GET /proof/{key}` - will query for a merkle proof of the given key, download block headers, and verify all the signatures of that block. After it is done, it will present you some json and a stamp that it your data is really safe and sound. - -## Configuring - -When you instantiate a server, make sure to pass in application-specific info in order to properly. Like the following info: - -Possibly as command-line flags: - -* Where to store the private keys? (or find existing ones) -* Which type of key to generate? -* What is the URL of the tendermint RPC server? - * TODO: support multiple node URLs and round-robin -* What is the chain_id we wish to connect to? - -Extra code (plugin) you must write: - -* Logic to parse json -> `Signable` transaction -* Logic to parse binary values from merkle tree -> `struct`ured data to render - -TODO: - -* How to get the trusted validator set? diff --git a/server/README.md b/server/README.md new file mode 100644 index 000000000..032cf574e --- /dev/null +++ b/server/README.md @@ -0,0 +1,13 @@ +# Proxy Server + +This package provides all the functionality for a local http server, providing access to key management functionality (creating, listing, updating, and deleting keys). This is a nice building block for larger apps, and the HTTP handlers here can be embedded in a larger server that does nice things like signing transactions and posting them to a tendermint chain (which requires domain-knowledge of the transactions types and out of scope of this generic app). + +## Key Management + +We expose a number of methods for safely managing your keychain. If you are embedding this in a larger server, you will typically want to mount all these paths under `/keys`. + +* `POST /` - provide a name and passphrase and create a brand new key +* `GET /` - get a list of all available key names, along with their public key and address +* `GET /{name}` - get public key and address for this named key +* `PUT /{name}` - update the passphrase for the given key. requires you to correctly provide the current passphrase, as well as a new one. +* `DELETE /{name}` - permanently delete this private key. requires you to correctly provide the current passphrase diff --git a/proxy/helpers.go b/server/helpers.go similarity index 90% rename from proxy/helpers.go rename to server/helpers.go index ac314684b..111f158e7 100644 --- a/proxy/helpers.go +++ b/server/helpers.go @@ -1,11 +1,11 @@ /* -package proxy provides http handlers to construct a proxy server +package server provides http handlers to construct a server server for key management, transaction signing, and query validation. Please read the README and godoc to see how to configure the server for your application. */ -package proxy +package server import ( "encoding/json" @@ -13,7 +13,7 @@ import ( "net/http" data "github.com/tendermint/go-data" - "github.com/tendermint/go-keys/proxy/types" + "github.com/tendermint/go-keys/server/types" "github.com/pkg/errors" ) diff --git a/proxy/keys.go b/server/keys.go similarity index 77% rename from proxy/keys.go rename to server/keys.go index 0dde57074..78a382e5e 100644 --- a/proxy/keys.go +++ b/server/keys.go @@ -1,4 +1,4 @@ -package proxy +package server import ( "errors" @@ -6,22 +6,22 @@ import ( "github.com/gorilla/mux" keys "github.com/tendermint/go-keys" - "github.com/tendermint/go-keys/proxy/types" + "github.com/tendermint/go-keys/server/types" ) -type KeyServer struct { +type Keys struct { manager keys.Manager algo string } -func NewKeyServer(manager keys.Manager, algo string) KeyServer { - return KeyServer{ +func New(manager keys.Manager, algo string) Keys { + return Keys{ manager: manager, algo: algo, } } -func (k KeyServer) GenerateKey(w http.ResponseWriter, r *http.Request) { +func (k Keys) GenerateKey(w http.ResponseWriter, r *http.Request) { req := types.CreateKeyRequest{ Algo: k.algo, // default key type from cli } @@ -40,7 +40,7 @@ func (k KeyServer) GenerateKey(w http.ResponseWriter, r *http.Request) { writeSuccess(w, &key) } -func (k KeyServer) GetKey(w http.ResponseWriter, r *http.Request) { +func (k Keys) GetKey(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) name := vars["name"] key, err := k.manager.Get(name) @@ -51,7 +51,7 @@ func (k KeyServer) GetKey(w http.ResponseWriter, r *http.Request) { writeSuccess(w, &key) } -func (k KeyServer) ListKeys(w http.ResponseWriter, r *http.Request) { +func (k Keys) ListKeys(w http.ResponseWriter, r *http.Request) { keys, err := k.manager.List() if err != nil { @@ -61,7 +61,7 @@ func (k KeyServer) ListKeys(w http.ResponseWriter, r *http.Request) { writeSuccess(w, keys) } -func (k KeyServer) UpdateKey(w http.ResponseWriter, r *http.Request) { +func (k Keys) UpdateKey(w http.ResponseWriter, r *http.Request) { req := types.UpdateKeyRequest{} err := readRequest(r, &req) if err != nil { @@ -90,7 +90,7 @@ func (k KeyServer) UpdateKey(w http.ResponseWriter, r *http.Request) { writeSuccess(w, &key) } -func (k KeyServer) DeleteKey(w http.ResponseWriter, r *http.Request) { +func (k Keys) DeleteKey(w http.ResponseWriter, r *http.Request) { req := types.DeleteKeyRequest{} err := readRequest(r, &req) if err != nil { @@ -118,7 +118,7 @@ func (k KeyServer) DeleteKey(w http.ResponseWriter, r *http.Request) { writeSuccess(w, &resp) } -func (k KeyServer) Register(r *mux.Router) { +func (k Keys) Register(r *mux.Router) { r.HandleFunc("/", k.GenerateKey).Methods("POST") r.HandleFunc("/", k.ListKeys).Methods("GET") r.HandleFunc("/{name}", k.GetKey).Methods("GET") diff --git a/proxy/keys_test.go b/server/keys_test.go similarity index 96% rename from proxy/keys_test.go rename to server/keys_test.go index 3a9c73717..8333e8e53 100644 --- a/proxy/keys_test.go +++ b/server/keys_test.go @@ -1,4 +1,4 @@ -package proxy_test +package server_test import ( "bytes" @@ -12,8 +12,8 @@ import ( "github.com/stretchr/testify/require" keys "github.com/tendermint/go-keys" "github.com/tendermint/go-keys/cryptostore" - "github.com/tendermint/go-keys/proxy" - "github.com/tendermint/go-keys/proxy/types" + "github.com/tendermint/go-keys/server" + "github.com/tendermint/go-keys/server/types" "github.com/tendermint/go-keys/storage/memstorage" ) @@ -92,7 +92,7 @@ func setupServer() http.Handler { ) // build your http server - ks := proxy.NewKeyServer(cstore, "ed25519") + ks := server.New(cstore, "ed25519") r := mux.NewRouter() sk := r.PathPrefix("/keys").Subrouter() ks.Register(sk) diff --git a/proxy/types/keys.go b/server/types/keys.go similarity index 100% rename from proxy/types/keys.go rename to server/types/keys.go diff --git a/proxy/valid.go b/server/valid.go similarity index 92% rename from proxy/valid.go rename to server/valid.go index 31782cfca..50b51e21b 100644 --- a/proxy/valid.go +++ b/server/valid.go @@ -1,4 +1,4 @@ -package proxy +package server import ( "github.com/pkg/errors"