/
vaultServe.go
146 lines (120 loc) · 3.83 KB
/
vaultServe.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// Copyright © 2018 EOS Canada <info@eoscanada.com>
package cmd
import (
"encoding/json"
"fmt"
"log"
"net/http"
"github.com/eoscanada/eos-go"
"github.com/eoscanada/eos-go/ecc"
"eosc/cli"
eosvault "eosc/vault"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
// vaultServeCmd represents the serve command
var vaultServeCmd = &cobra.Command{
Use: "serve",
Short: "Serves signing queries on a local port.",
Long: `Serve will start listening on a local port, offering a
keosd-compatible interface, ready to sign transactions.
It is to be used with tools such as 'cleos' or 'eos-vote' that need
transactions signed before submitting them to an EOS network.
`,
Run: func(cmd *cobra.Command, args []string) {
vault := mustGetWallet()
vault.PrintPublicKeys()
listen(vault)
},
}
func init() {
vaultCmd.AddCommand(vaultServeCmd)
vaultServeCmd.Flags().IntP("port", "", 6666, "Listen port")
vaultServeCmd.Flags().BoolP("auto-accept", "", false, "Whether to auto accept all signature requests, or to ask for a security code on the command line.")
for _, flag := range []string{"port", "auto-accept"} {
if err := viper.BindPFlag("vault-serve-cmd-"+flag, vaultServeCmd.Flags().Lookup(flag)); err != nil {
panic(err)
}
}
}
func listen(v *eosvault.Vault) {
http.HandleFunc("/v1/wallet/get_public_keys", func(w http.ResponseWriter, r *http.Request) {
//fmt.Println("Service /v1/wallet/get_public_keys")
var out []string
for _, key := range v.KeyBag.Keys {
out = append(out, key.PublicKey().String())
}
json.NewEncoder(w).Encode(out)
})
http.HandleFunc("/v1/wallet/sign_transaction", func(w http.ResponseWriter, r *http.Request) {
fmt.Println("Incoming signature request")
var inputs []json.RawMessage
if err := json.NewDecoder(r.Body).Decode(&inputs); err != nil {
fmt.Println("sign_transaction: error:", err)
http.Error(w, "couldn't decode input", 500)
return
}
var tx *eos.SignedTransaction
var requiredKeys []ecc.PublicKey
var chainID eos.HexBytes
if len(inputs) != 3 {
http.Error(w, "invalid length of message, should be 3 parameters", 500)
return
}
err := json.Unmarshal(inputs[0], &tx)
if err != nil {
http.Error(w, "decoding transaction", 500)
return
}
err = json.Unmarshal(inputs[1], &requiredKeys)
if err != nil {
http.Error(w, "decoding required keys", 500)
return
}
err = json.Unmarshal(inputs[2], &chainID)
if err != nil {
http.Error(w, "decoding chain id", 500)
return
}
fmt.Println("")
if !viper.GetBool("vault-serve-cmd-auto-accept") {
res, err := cli.GetConfirmation(`- Enter the code "%d" to allow signature: `)
if err != nil {
fmt.Println("sign_transaction: error reading confirmation from command line:", err)
http.Error(w, "error reading confirmation from command line", 500)
return
}
if !res {
fmt.Println("sign_transaction: security code invalid, not signing request")
http.Error(w, "security code invalid, not signing request", 401)
return
}
} else {
fmt.Println("- Auto-signing request")
}
signed, err := v.KeyBag.Sign(tx, chainID, requiredKeys...)
for _, action := range signed.Transaction.Actions {
action.SetToServer(false)
}
if err != nil {
http.Error(w, fmt.Sprintf("error signing: %s", err), 500)
return
}
cnt, err := json.Marshal(signed)
if err != nil {
http.Error(w, fmt.Sprintf("couldn't marshal output: %s", err), 500)
return
}
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(cnt)))
w.WriteHeader(201)
_, err = w.Write(cnt)
if err != nil {
log.Println("Error writing to socket:", err)
}
})
port := viper.GetInt("vault-serve-cmd-port")
fmt.Printf("Listening for wallet operations on 127.0.0.1:%d\n", port)
if err := http.ListenAndServe(fmt.Sprintf("127.0.0.1:%d", port), nil); err != nil {
fmt.Printf("Failed listening on port %d: %s\n", port, err)
}
}