OSDN Git Service

Merge branch 'dev' into dev-verify
[bytom/bytom.git] / account / image.go
1 // Package account stores and tracks accounts within a Bytom Core.
2 package account
3
4 import (
5         "encoding/json"
6
7         log "github.com/sirupsen/logrus"
8
9         "github.com/bytom/common"
10 )
11
12 // ImageSlice record info of single account
13 type ImageSlice struct {
14         Account       *Account `json:"account"`
15         ContractIndex uint64   `json:"contract_index"`
16 }
17
18 // Image is the struct for hold export account data
19 type Image struct {
20         Slice []*ImageSlice `json:"slices"`
21 }
22
23 // Backup export all the account info into image
24 func (m *Manager) Backup() (*Image, error) {
25         image := &Image{
26                 Slice: []*ImageSlice{},
27         }
28
29         accountIter := m.db.IteratorPrefix(accountPrefix)
30         defer accountIter.Release()
31         for accountIter.Next() {
32                 a := &Account{}
33                 if err := json.Unmarshal(accountIter.Value(), a); err != nil {
34                         return nil, err
35                 }
36
37                 image.Slice = append(image.Slice, &ImageSlice{
38                         Account:       a,
39                         ContractIndex: m.getNextContractIndex(a.ID),
40                 })
41         }
42         return image, nil
43 }
44
45 // Restore import the accountImages into account manage
46 func (m *Manager) Restore(image *Image) error {
47         maxAccountIndex := uint64(0)
48         storeBatch := m.db.NewBatch()
49         for _, slice := range image.Slice {
50                 if existed := m.db.Get(Key(slice.Account.ID)); existed != nil {
51                         log.WithFields(log.Fields{
52                                 "alias": slice.Account.Alias,
53                                 "id":    slice.Account.ID,
54                         }).Warning("skip restore account due to already existed")
55                         continue
56                 }
57                 if existed := m.db.Get(aliasKey(slice.Account.Alias)); existed != nil {
58                         return ErrDuplicateAlias
59                 }
60
61                 rawAccount, err := json.Marshal(slice.Account)
62                 if err != nil {
63                         return ErrMarshalAccount
64                 }
65
66                 if slice.Account.Signer.KeyIndex > maxAccountIndex {
67                         maxAccountIndex = slice.Account.Signer.KeyIndex
68                 }
69                 storeBatch.Set(Key(slice.Account.ID), rawAccount)
70                 storeBatch.Set(aliasKey(slice.Account.Alias), []byte(slice.Account.ID))
71         }
72
73         if localIndex := m.getNextAccountIndex(); localIndex < maxAccountIndex {
74                 storeBatch.Set(accountIndexKey, common.Unit64ToBytes(maxAccountIndex))
75         }
76         storeBatch.Write()
77
78         for _, slice := range image.Slice {
79                 for i := uint64(1); i <= slice.ContractIndex; i++ {
80                         if _, err := m.createAddress(nil, slice.Account, false); err != nil {
81                                 return err
82                         }
83                 }
84         }
85         return nil
86 }