OSDN Git Service

Merge pull request #38 from Bytom/dev_module_cliam
[bytom/vapor.git] / api / hsm.go
1 package api
2
3 import (
4         "context"
5
6         log "github.com/sirupsen/logrus"
7
8         "github.com/vapor/blockchain/pseudohsm"
9         "github.com/vapor/blockchain/txbuilder"
10         "github.com/vapor/common"
11         "github.com/vapor/consensus"
12         "github.com/vapor/crypto"
13         "github.com/vapor/crypto/ed25519/chainkd"
14 )
15
16 type createKeyResp struct {
17         Alias    string       `json:"alias"`
18         XPub     chainkd.XPub `json:"xpub"`
19         File     string       `json:"file"`
20         Mnemonic string       `json:"mnemonic,omitempty"`
21 }
22
23 func (a *API) pseudohsmCreateKey(ctx context.Context, in struct {
24         Alias    string `json:"alias"`
25         Password string `json:"password"`
26         Mnemonic string `json:"mnemonic"`
27         Language string `json:"language"`
28 }) Response {
29         if in.Language == "" {
30                 in.Language = "en"
31         }
32         if len(in.Mnemonic) > 0 {
33                 xpub, err := a.wallet.Hsm.ImportKeyFromMnemonic(in.Alias, in.Password, in.Mnemonic, in.Language)
34                 if err != nil {
35                         return NewErrorResponse(err)
36                 }
37                 return NewSuccessResponse(&createKeyResp{Alias: xpub.Alias, XPub: xpub.XPub, File: xpub.File})
38         }
39         xpub, mnemonic, err := a.wallet.Hsm.XCreate(in.Alias, in.Password, in.Language)
40         if err != nil {
41                 return NewErrorResponse(err)
42         }
43         return NewSuccessResponse(&createKeyResp{Alias: xpub.Alias, XPub: xpub.XPub, File: xpub.File, Mnemonic: *mnemonic})
44 }
45
46 func (a *API) pseudohsmUpdateKeyAlias(ctx context.Context, in struct {
47         XPub     chainkd.XPub `json:"xpub"`
48         NewAlias string       `json:"new_alias"`
49 }) Response {
50         if err := a.wallet.Hsm.UpdateKeyAlias(in.XPub, in.NewAlias); err != nil {
51                 return NewErrorResponse(err)
52         }
53         return NewSuccessResponse(nil)
54 }
55
56 func (a *API) pseudohsmListKeys(ctx context.Context) Response {
57         return NewSuccessResponse(a.wallet.Hsm.ListKeys())
58 }
59
60 func (a *API) pseudohsmDeleteKey(ctx context.Context, x struct {
61         Password string       `json:"password"`
62         XPub     chainkd.XPub `json:"xpub"`
63 }) Response {
64         if err := a.wallet.Hsm.XDelete(x.XPub, x.Password); err != nil {
65                 return NewErrorResponse(err)
66         }
67         return NewSuccessResponse(nil)
68 }
69
70 type signTemplateResp struct {
71         Tx           *txbuilder.Template `json:"transaction"`
72         SignComplete bool                `json:"sign_complete"`
73 }
74
75 func (a *API) signTemplate(ctx context.Context, x struct {
76         Password string             `json:"password"`
77         Txs      txbuilder.Template `json:"transaction"`
78 }) Response {
79         if err := txbuilder.Sign(ctx, &x.Txs, x.Password, a.PseudohsmSignTemplate); err != nil {
80                 log.WithField("build err", err).Error("fail on sign transaction.")
81                 return NewErrorResponse(err)
82         }
83         log.Info("Sign Transaction complete.")
84         return NewSuccessResponse(&signTemplateResp{Tx: &x.Txs, SignComplete: txbuilder.SignProgress(&x.Txs)})
85 }
86
87 func (a *API) signWithPriKey(ins struct {
88         Xprv string             `json:"xprv"`
89         Tx   txbuilder.Template `json:"transaction"`
90 }) Response {
91         xprv := &chainkd.XPrv{}
92         if err := xprv.UnmarshalText([]byte(ins.Xprv)); err != nil {
93                 return NewErrorResponse(err)
94         }
95         if err := pseudohsm.SignWithKey(&ins.Tx, *xprv); err != nil {
96                 return NewErrorResponse(err)
97         }
98         log.Info("Sign Transaction complete.")
99         return NewSuccessResponse(&signTemplateResp{Tx: &ins.Tx, SignComplete: txbuilder.SignProgress(&ins.Tx)})
100 }
101
102 type signTemplatesResp struct {
103         Tx           []*txbuilder.Template `json:"transaction"`
104         SignComplete bool                  `json:"sign_complete"`
105 }
106
107 func (a *API) signTemplates(ctx context.Context, x struct {
108         Password string                `json:"password"`
109         Txs      []*txbuilder.Template `json:"transactions"`
110 }) Response {
111         signComplete := true
112         for _, tx := range x.Txs {
113                 if err := txbuilder.Sign(ctx, tx, x.Password, a.PseudohsmSignTemplate); err != nil {
114                         log.WithField("build err", err).Error("fail on sign transaction.")
115                         return NewErrorResponse(err)
116                 }
117                 signComplete = signComplete && txbuilder.SignProgress(tx)
118         }
119
120         log.Info("Sign Chain Tx complete.")
121         return NewSuccessResponse(&signTemplatesResp{Tx: x.Txs, SignComplete: signComplete})
122 }
123
124 func (a *API) PseudohsmSignTemplate(ctx context.Context, xpub chainkd.XPub, path [][]byte, data [32]byte, password string) ([]byte, error) {
125         return a.wallet.Hsm.XSign(xpub, path, data[:], password)
126 }
127
128 // ResetPasswordResp is response for reset key password
129 type ResetPasswordResp struct {
130         Changed bool `json:"changed"`
131 }
132
133 func (a *API) pseudohsmResetPassword(ctx context.Context, ins struct {
134         XPub        chainkd.XPub `json:"xpub"`
135         OldPassword string       `json:"old_password"`
136         NewPassword string       `json:"new_password"`
137 }) Response {
138         resp := &ResetPasswordResp{Changed: false}
139         if err := a.wallet.Hsm.ResetPassword(ins.XPub, ins.OldPassword, ins.NewPassword); err != nil {
140                 return NewSuccessResponse(resp)
141         }
142         resp.Changed = true
143         return NewSuccessResponse(resp)
144 }
145
146 // CheckPasswordResp is response for check key password
147 type CheckPasswordResp struct {
148         CheckResult bool `json:"check_result"`
149 }
150
151 func (a *API) pseudohsmCheckPassword(ctx context.Context, ins struct {
152         XPub     chainkd.XPub `json:"xpub"`
153         Password string       `json:"password"`
154 }) Response {
155         resp := &CheckPasswordResp{CheckResult: false}
156         if _, err := a.wallet.Hsm.LoadChainKDKey(ins.XPub, ins.Password); err != nil {
157                 return NewSuccessResponse(resp)
158         }
159         resp.CheckResult = true
160         return NewSuccessResponse(resp)
161 }
162
163 type keyPair struct {
164         Xpub    chainkd.XPub `json:"xpub"`
165         Xprv    chainkd.XPrv `json:"xprv"`
166         Address string       `json:"address,omitempty"`
167 }
168
169 func (a *API) createXKeys(ctx context.Context) Response {
170         xprv, xpub, err := chainkd.NewXKeys(nil)
171         if err != nil {
172                 return NewErrorResponse(err)
173         }
174
175         pubHash := crypto.Ripemd160(xpub.PublicKey())
176
177         address, err := common.NewAddressWitnessPubKeyHash(pubHash, &consensus.ActiveNetParams)
178         if err != nil {
179                 return NewErrorResponse(err)
180         }
181
182         return NewSuccessResponse(&keyPair{Xprv: xprv, Xpub: xpub, Address: address.EncodeAddress()})
183 }