hermez-node/db/statedb/statedb.go
db/statedb/statedb.goRaw
1package statedb
2
3import (
4 "errors"
5
6 "github.com/hermeznetwork/hermez-node/common"
7 "github.com/iden3/go-merkletree"
8 "github.com/iden3/go-merkletree/db"
9 "github.com/iden3/go-merkletree/db/leveldb"
10 "github.com/iden3/go-merkletree/db/memory"
11)
12
13// ErrStateDBWithoutMT is used when a method that requires a MerkleTree is called in a StateDB that does not have a MerkleTree defined
14var ErrStateDBWithoutMT = errors.New("Can not call method to use MerkleTree in a StateDB without MerkleTree")
15
16// ErrAccountAlreadyExists is used when CreateAccount is called and the Account already exists
17var ErrAccountAlreadyExists = errors.New("Can not CreateAccount because Account already exists")
18
19// StateDB represents the StateDB object
20type StateDB struct {
21 db db.Storage
22 mt *merkletree.MerkleTree
23}
24
25// NewStateDB creates a new StateDB, allowing to use an in-memory or in-disk
26// storage
27func NewStateDB(path string, inDisk bool, withMT bool, nLevels int) (*StateDB, error) {
28 var sto db.Storage
29 var err error
30 if inDisk {
31 sto, err = leveldb.NewLevelDbStorage(path, false)
32 if err != nil {
33 return nil, err
34 }
35 } else {
36 sto = memory.NewMemoryStorage()
37 }
38 var mt *merkletree.MerkleTree = nil
39 if withMT {
40 mt, err = merkletree.NewMerkleTree(sto, nLevels)
41 if err != nil {
42 return nil, err
43 }
44 }
45
46 return &StateDB{
47 db: sto,
48 mt: mt,
49 }, nil
50}
51
52// CheckPointAt does a checkpoint at the given batchNum in the defined path
53func (s *StateDB) CheckPointAt(batchNum int, path string) error {
54 // TODO
55
56 return nil
57}
58
59// Reset resets the StateDB to the checkpoint at the given batchNum
60func (s *StateDB) Reset(batchNum int) error {
61 // TODO
62
63 return nil
64}
65
66// Checkpoints returns a list of the checkpoints (batchNums)
67func (s *StateDB) Checkpoints() ([]int, error) {
68 // TODO
69
70 //batchnums, err
71 return nil, nil
72}
73
74// GetAccount returns the account for the given Idx
75func (s *StateDB) GetAccount(idx common.Idx) (*common.Account, error) {
76 vBytes, err := s.db.Get(idx.Bytes())
77 if err != nil {
78 return nil, err
79 }
80 accBytes, err := s.db.Get(vBytes)
81 if err != nil {
82 return nil, err
83 }
84 var b [32 * common.NLEAFELEMS]byte
85 copy(b[:], accBytes)
86 return common.AccountFromBytes(b)
87}
88
89// CreateAccount creates a new Account in the StateDB for the given Idx.
90// MerkleTree is not affected.
91func (s *StateDB) CreateAccount(idx common.Idx, account *common.Account) error {
92 // store at the DB the key: v, and value: leaf.Bytes()
93 v, err := account.HashValue()
94 if err != nil {
95 return err
96 }
97 accountBytes, err := account.Bytes()
98 if err != nil {
99 return err
100 }
101
102 // store the Leaf value
103 tx, err := s.db.NewTx()
104 if err != nil {
105 return err
106 }
107
108 _, err = tx.Get(idx.Bytes())
109 if err != db.ErrNotFound {
110 return ErrAccountAlreadyExists
111 }
112
113 tx.Put(v.Bytes(), accountBytes[:])
114 tx.Put(idx.Bytes(), v.Bytes())
115
116 return tx.Commit()
117}
118
119// UpdateAccount updates the Account in the StateDB for the given Idx.
120// MerkleTree is not affected.
121func (s *StateDB) UpdateAccount(idx common.Idx, account *common.Account) error {
122 // store at the DB the key: v, and value: leaf.Bytes()
123 v, err := account.HashValue()
124 if err != nil {
125 return err
126 }
127 accountBytes, err := account.Bytes()
128 if err != nil {
129 return err
130 }
131
132 tx, err := s.db.NewTx()
133 if err != nil {
134 return err
135 }
136 tx.Put(v.Bytes(), accountBytes[:])
137 tx.Put(idx.Bytes(), v.Bytes())
138
139 return tx.Commit()
140}
141
142// MTCreateAccount creates a new Account in the StateDB for the given Idx,
143// and updates the MerkleTree, returning a CircomProcessorProof
144func (s *StateDB) MTCreateAccount(idx common.Idx, account *common.Account) (*merkletree.CircomProcessorProof, error) {
145 if s.mt == nil {
146 return nil, ErrStateDBWithoutMT
147 }
148 err := s.CreateAccount(idx, account)
149 if err != nil {
150 return nil, err
151 }
152
153 v, err := account.HashValue() // already computed in s.CreateAccount, next iteration reuse first computation
154 if err != nil {
155 return nil, err
156 }
157 // Add k & v into the MT
158 return s.mt.AddAndGetCircomProof(idx.BigInt(), v)
159}
160
161// MTUpdateAccount updates the Account in the StateDB for the given Idx, and
162// updates the MerkleTree, returning a CircomProcessorProof
163func (s *StateDB) MTUpdateAccount(idx common.Idx, account *common.Account) (*merkletree.CircomProcessorProof, error) {
164 if s.mt == nil {
165 return nil, ErrStateDBWithoutMT
166 }
167 err := s.UpdateAccount(idx, account)
168 if err != nil {
169 return nil, err
170 }
171
172 v, err := account.HashValue() // already computed in s.CreateAccount, next iteration reuse first computation
173 if err != nil {
174 return nil, err
175 }
176 // Add k & v into the MT
177 return s.mt.Update(idx.BigInt(), v)
178}
179
180// MTGetProof returns the CircomVerifierProof for a given Idx
181func (s *StateDB) MTGetProof(idx common.Idx) (*merkletree.CircomVerifierProof, error) {
182 if s.mt == nil {
183 return nil, ErrStateDBWithoutMT
184 }
185 return s.mt.GenerateCircomVerifierProof(idx.BigInt(), s.mt.Root())
186}
187
188// LocalStateDB represents the local StateDB which allows to make copies from
189// the synchronizer StateDB, and is used by the tx-selector and the
190// batch-builder. LocalStateDB is an in-memory storage.
191type LocalStateDB struct {
192 *StateDB
193 synchronizerStateDB *StateDB
194}
195
196// NewLocalStateDB returns a new LocalStateDB connected to the given
197// synchronizerDB
198func NewLocalStateDB(synchronizerDB *StateDB, withMT bool, nLevels int) (*LocalStateDB, error) {
199 s, err := NewStateDB("", false, withMT, nLevels)
200 if err != nil {
201 return nil, err
202 }
203 return &LocalStateDB{
204 s,
205 synchronizerDB,
206 }, nil
207}
208
209// Reset performs a reset, getting the state from
210// LocalStateDB.synchronizerStateDB for the given batchNum
211func (l *LocalStateDB) Reset(batchNum int, fromSynchronizer bool) error {
212 // TODO
213
214 return nil
215}