github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/account/manager_file.go (about) 1 // Copyright (C) 2017 go-crystal authors 2 // 3 // This file is part of the go-crystal library. 4 // 5 // the go-crystal library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // the go-crystal library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with the go-crystal library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 19 package account 20 21 import ( 22 "encoding/json" 23 "errors" 24 "fmt" 25 "github.com/sixexorg/magnetic-ring/common" 26 "github.com/sixexorg/magnetic-ring/log" 27 "io/ioutil" 28 "os" 29 "path/filepath" 30 "strings" 31 ) 32 33 type account struct { 34 35 // key address 36 addr common.Address 37 38 // key save path 39 path string 40 } 41 42 func checkMake(dir string) error { 43 _,err := os.Stat(dir) 44 if err != nil { 45 err = os.Mkdir(dir,os.ModePerm) 46 if err != nil { 47 return err 48 } 49 } 50 return nil 51 } 52 53 // refreshAccounts sync key files to memory 54 func (m *AccountManagerImpl) refreshAccounts() error { 55 err := checkMake(m.keydir) 56 if err != nil { 57 return err 58 } 59 files, err := ioutil.ReadDir(m.keydir) 60 if err != nil { 61 return err 62 } 63 var accounts []*account 64 65 66 for _, file := range files { 67 68 acc, err := m.loadKeyFile(file) 69 if err != nil { 70 // errors have been recorded 71 72 continue 73 } 74 accounts = append(accounts, acc) 75 } 76 77 m.accounts = accounts 78 return nil 79 } 80 81 func (m *AccountManagerImpl) refreshMulTmplts() error { 82 err := checkMake(m.multiAddrDir) 83 if err != nil { 84 return err 85 } 86 files, err := ioutil.ReadDir(m.multiAddrDir) 87 if err != nil { 88 return err 89 } 90 91 92 for _, file := range files { 93 94 if file.IsDir(){ 95 childPath := filepath.Join(m.multiAddrDir,file.Name()) 96 fs, err := ioutil.ReadDir(childPath) 97 if err != nil { 98 log.Info("read childPath error","manager_file",err) 99 continue 100 } 101 for _,f := range fs { 102 mpk,err := m.loadMultiTmpltFile(file.Name(),f) 103 if err !=nil { 104 log.Info("load multi tmplt file err","refreshMultmplts",err) 105 continue 106 } 107 units,err := mpk.Tmplt.ToMultiAccUnits() 108 if err !=nil { 109 log.Info("mpk.Tmplt.ToMultiAccUnits err","refreshMultmplts",err) 110 continue 111 } 112 113 mulac := new(MultipleAccountImpl) 114 mulac.Maus = units 115 tempaddress,err := units.Address() 116 if err != nil { 117 log.Info("units.Address err","refreshMultmplts",err) 118 continue 119 } 120 mulac.Addr=&tempaddress 121 122 123 124 if mulmap, ok := m.acctMulMap[file.Name()]; !ok { 125 mulmap = make(MultiMap) 126 127 mulmap[mulac.Addr.ToString()] = *mulac 128 m.acctMulMap[file.Name()] = mulmap 129 130 } else { 131 mulmap[mpk.Mulstr] = *mulac 132 } 133 } 134 } 135 136 } 137 return nil 138 } 139 140 func (m *AccountManagerImpl) loadKeyFile(file os.FileInfo) (*account, error) { 141 var ( 142 keyJSON struct { 143 Address string `json:"address"` 144 } 145 ) 146 147 path := filepath.Join(m.keydir, file.Name()) 148 149 if file.IsDir() || strings.HasPrefix(file.Name(), ".") || strings.HasSuffix(file.Name(), "~") { 150 //logging.VLog().WithFields(logrus.Fields{ 151 // "path": path, 152 //}).Warn("Skipped this key file.") 153 return nil, errors.New("file need skip") 154 } 155 156 raw, err := ioutil.ReadFile(path) 157 if err != nil { 158 //logging.VLog().WithFields(logrus.Fields{ 159 // "err": err, 160 // "path": path, 161 //}).Error("Failed to read the key file.") 162 return nil, errors.New("failed to read the key file") 163 } 164 165 keyJSON.Address = "" 166 err = json.Unmarshal(raw, &keyJSON) 167 if err != nil { 168 //logging.VLog().WithFields(logrus.Fields{ 169 // "err": err, 170 // "path": path, 171 //}).Error("Failed to parse the key file.") 172 return nil, errors.New("failed to parse the key file") 173 } 174 175 addr, err := common.ToAddress(keyJSON.Address) 176 if err != nil { 177 //logging.VLog().WithFields(logrus.Fields{ 178 // "err": err, 179 // "address": keyJSON.Address, 180 //}).Error("Failed to parse the address.") 181 return nil, errors.New("failed to parse the address") 182 } 183 184 185 acc := &account{addr, path} 186 return acc, nil 187 } 188 189 func (m *AccountManagerImpl) loadMultiTmpltFile(prepath string,file os.FileInfo) (*MulPack, error) { 190 path := filepath.Join(m.multiAddrDir,prepath,file.Name()) 191 192 if file.IsDir() || strings.HasPrefix(file.Name(), ".") || strings.HasSuffix(file.Name(), "~") { 193 //logging.VLog().WithFields(logrus.Fields{ 194 // "path": path, 195 //}).Warn("Skipped this key file.") 196 return nil, errors.New("file need skip") 197 } 198 199 raw, err := ioutil.ReadFile(path) 200 if err != nil { 201 //logging.VLog().WithFields(logrus.Fields{ 202 // "err": err, 203 // "path": path, 204 //}).Error("Failed to read the key file.") 205 return nil, errors.New("failed to read the key file") 206 } 207 208 obj := new(MulPack) 209 err = json.Unmarshal(raw,obj) 210 if err != nil { 211 fmt.Printf("decode err -->%v\n",err) 212 return nil,err 213 } 214 215 216 return obj, nil 217 } 218 219 // loadFile import key to keystore in keydir 220 func (m *AccountManagerImpl) loadFile(addr common.Address, passphrase []byte) error { 221 acc, err := m.getAccount(addr) 222 if err != nil { 223 return err 224 } 225 226 raw, err := ioutil.ReadFile(acc.path) 227 if err != nil { 228 return err 229 } 230 _, err = m.Load(raw, passphrase) 231 return err 232 } 233 234 func (am *AccountManagerImpl) ImportNormalAccount(filePath, password string) (common.Address,error) { 235 empty := common.Address{} 236 raw, err := ioutil.ReadFile(filePath) 237 if err != nil { 238 return empty,err 239 } 240 passphrase := []byte(password) 241 acct, err := am.Load(raw, passphrase) 242 243 if err != nil { 244 return empty,err 245 } 246 247 return acct,nil 248 } 249 250 func (m *AccountManagerImpl) ExportNormalAccount(na NormalAccount, filePath, password string,overwrite bool) error { 251 passphrase := []byte(password) 252 addr := na.Address() 253 raw, err := m.Export(addr, passphrase) 254 if err != nil { 255 return err 256 } 257 258 //acc, err := m.getAccount(&addr) 259 // acc not found 260 261 if err := common.FileWrite(filePath, raw, overwrite); err != nil { 262 return err 263 } 264 return nil 265 } 266 267 func (m *AccountManagerImpl) exportFile(addr common.Address, passphrase []byte, overwrite bool) (path string, err error) { 268 raw, err := m.Export(addr, passphrase) 269 if err != nil { 270 return "", err 271 } 272 273 acc, err := m.getAccount(addr) 274 // acc not found 275 if err != nil { 276 path = filepath.Join(m.keydir, addr.ToString()) 277 } else { 278 path = acc.path 279 } 280 if err := common.FileWrite(path, raw, overwrite); err != nil { 281 return "", err 282 } 283 return path, nil 284 } 285 286 func (m *AccountManagerImpl) getAccount(addr common.Address) (*account, error) { 287 m.mutex.Lock() 288 defer m.mutex.Unlock() 289 290 for _, acc := range m.accounts { 291 if acc.addr.Equals(addr) { 292 return acc, nil 293 } 294 } 295 return nil, errors.New("account not found") 296 } 297 298 func (m *AccountManagerImpl) updateAccount(addr common.Address, path string) { 299 m.mutex.Lock() 300 defer m.mutex.Unlock() 301 302 var target *account 303 for _, acc := range m.accounts { 304 if acc.addr.Equals(addr) { 305 target = acc 306 break 307 } 308 } 309 if target != nil { 310 target.path = path 311 } else { 312 target = &account{addr: addr, path: path} 313 m.accounts = append(m.accounts, target) 314 } 315 }