OSDN Git Service

Merge pull request #375 from Bytom/dev
[bytom/bytom.git] / blockchain / rpc_reactor.go
1 package blockchain
2
3 import (
4         "net/http"
5         "time"
6
7         log "github.com/sirupsen/logrus"
8
9         "github.com/bytom/blockchain/accesstoken"
10         "github.com/bytom/dashboard"
11         "github.com/bytom/errors"
12         "github.com/bytom/net/http/authn"
13         "github.com/bytom/net/http/httpjson"
14         "github.com/bytom/net/http/static"
15 )
16
17 var (
18         errNotAuthenticated = errors.New("not authenticated")
19 )
20
21 // json handler
22 func jsonHandler(f interface{}) http.Handler {
23         h, err := httpjson.Handler(f, errorFormatter.Write)
24         if err != nil {
25                 panic(err)
26         }
27         return h
28 }
29
30 // error handler
31 func alwaysError(err error) http.Handler {
32         return jsonHandler(func() error { return err })
33 }
34
35 // serve http
36 func (bcr *BlockchainReactor) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
37         if bcr.handler != nil {
38                 bcr.handler.ServeHTTP(rw, req)
39         }
40 }
41
42 func webAssetsHandler(next http.Handler) http.Handler {
43         mux := http.NewServeMux()
44         mux.Handle("/dashboard/", http.StripPrefix("/dashboard/", static.Handler{
45                 Assets:  dashboard.Files,
46                 Default: "index.html",
47         }))
48         mux.Handle("/", next)
49
50         return mux
51 }
52
53 // BuildHandler is in charge of all the rpc handling.
54 func (bcr *BlockchainReactor) BuildHandler() {
55         m := bcr.mux
56         if bcr.accounts != nil && bcr.assets != nil {
57                 m.Handle("/create-account", jsonHandler(bcr.createAccount))
58                 m.Handle("/update-account-tags", jsonHandler(bcr.updateAccountTags))
59                 m.Handle("/create-account-address", jsonHandler(bcr.createAccountAddress))
60                 m.Handle("/list-accounts", jsonHandler(bcr.listAccounts))
61                 m.Handle("/delete-account", jsonHandler(bcr.deleteAccount))
62
63                 m.Handle("/create-asset", jsonHandler(bcr.createAsset))
64                 m.Handle("/update-asset-alias", jsonHandler(bcr.updateAssetAlias))
65                 m.Handle("/update-asset-tags", jsonHandler(bcr.updateAssetTags))
66                 m.Handle("/list-assets", jsonHandler(bcr.listAssets))
67
68                 m.Handle("/create-key", jsonHandler(bcr.pseudohsmCreateKey))
69                 m.Handle("/list-keys", jsonHandler(bcr.pseudohsmListKeys))
70                 m.Handle("/delete-key", jsonHandler(bcr.pseudohsmDeleteKey))
71
72                 m.Handle("/list-transactions", jsonHandler(bcr.listTransactions))
73                 m.Handle("/list-balances", jsonHandler(bcr.listBalances))
74                 m.Handle("/reset-password", jsonHandler(bcr.pseudohsmResetPassword))
75         } else {
76                 log.Warn("Please enable wallet")
77         }
78
79         m.Handle("/", alwaysError(errors.New("not Found")))
80
81         m.Handle("/build-transaction", jsonHandler(bcr.build))
82         m.Handle("/sign-transaction", jsonHandler(bcr.pseudohsmSignTemplates))
83         m.Handle("/submit-transaction", jsonHandler(bcr.submit))
84         m.Handle("/sign-submit-transaction", jsonHandler(bcr.signSubmit))
85
86         m.Handle("/create-transaction-feed", jsonHandler(bcr.createTxFeed))
87         m.Handle("/get-transaction-feed", jsonHandler(bcr.getTxFeed))
88         m.Handle("/update-transaction-feed", jsonHandler(bcr.updateTxFeed))
89         m.Handle("/delete-transaction-feed", jsonHandler(bcr.deleteTxFeed))
90         m.Handle("/list-transaction-feeds", jsonHandler(bcr.listTxFeeds))
91         m.Handle("/list-unspent-outputs", jsonHandler(bcr.listUnspentOutputs))
92         m.Handle("/info", jsonHandler(bcr.info))
93
94         m.Handle("/create-access-token", jsonHandler(bcr.createAccessToken))
95         m.Handle("/list-access-tokens", jsonHandler(bcr.listAccessTokens))
96         m.Handle("/delete-access-token", jsonHandler(bcr.deleteAccessToken))
97         m.Handle("/check-access-token", jsonHandler(bcr.checkAccessToken))
98
99         m.Handle("/block-hash", jsonHandler(bcr.getBestBlockHash))
100         m.Handle("/block-height", jsonHandler(bcr.blockHeight))
101
102         m.Handle("/export-private-key", jsonHandler(bcr.walletExportKey))
103         m.Handle("/import-private-key", jsonHandler(bcr.walletImportKey))
104         m.Handle("/import-key-progress", jsonHandler(bcr.keyImportProgress))
105
106         m.Handle("/get-block-header-by-hash", jsonHandler(bcr.getBlockHeaderByHash))
107         m.Handle("/get-block-by-hash", jsonHandler(bcr.getBlockByHash))
108         m.Handle("/get-block-by-height", jsonHandler(bcr.getBlockByHeight))
109         m.Handle("/get-block-transactions-count-by-hash", jsonHandler(bcr.getBlockTransactionsCountByHash))
110         m.Handle("/get-block-transactions-count-by-height", jsonHandler(bcr.getBlockTransactionsCountByHeight))
111
112         m.Handle("/net-info", jsonHandler(bcr.getNetInfo))
113
114         m.Handle("/is-mining", jsonHandler(bcr.isMining))
115         m.Handle("/gas-rate", jsonHandler(bcr.gasRate))
116         m.Handle("/get-work", jsonHandler(bcr.getWork))
117         m.Handle("/submit-work", jsonHandler(bcr.submitWork))
118
119         latencyHandler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
120                 if l := latency(m, req); l != nil {
121                         defer l.RecordSince(time.Now())
122                 }
123                 m.ServeHTTP(w, req)
124         })
125         handler := maxBytes(latencyHandler) // TODO(tessr): consider moving this to non-core specific mux
126         handler = webAssetsHandler(handler)
127
128         bcr.handler = handler
129 }
130
131 //AuthHandler access token auth handler
132 func AuthHandler(handler http.Handler, accessTokens *accesstoken.CredentialStore) http.Handler {
133
134         authenticator := authn.NewAPI(accessTokens)
135
136         return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
137                 // TODO(tessr): check that this path exists; return early if this path isn't legit
138                 req, err := authenticator.Authenticate(req)
139                 if err != nil {
140                         log.WithField("error", errors.Wrap(err, "Serve")).Error("Authenticate fail")
141                         err = errors.Sub(errNotAuthenticated, err)
142                         errorFormatter.Write(req.Context(), rw, err)
143                         return
144                 }
145                 handler.ServeHTTP(rw, req)
146         })
147 }