arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/db/statedb/statedb_test.go
db/statedb/statedb_test.goRaw
  1package statedb
  2
  3import (
  4	"encoding/hex"
  5	"fmt"
  6	"io/ioutil"
  7	"math/big"
  8	"os"
  9	"testing"
 10
 11	ethCrypto "github.com/ethereum/go-ethereum/crypto"
 12	"github.com/hermeznetwork/hermez-node/common"
 13	"github.com/iden3/go-iden3-crypto/babyjub"
 14	"github.com/iden3/go-merkletree/db"
 15	"github.com/stretchr/testify/assert"
 16	"github.com/stretchr/testify/require"
 17)
 18
 19func newAccount(t *testing.T, i int) *common.Account {
 20	var sk babyjub.PrivateKey
 21	_, err := hex.Decode(sk[:], []byte("0001020304050607080900010203040506070809000102030405060708090001"))
 22	require.Nil(t, err)
 23	pk := sk.Public()
 24
 25	key, err := ethCrypto.GenerateKey()
 26	require.Nil(t, err)
 27	address := ethCrypto.PubkeyToAddress(key.PublicKey)
 28
 29	return &common.Account{
 30		Idx:       common.Idx(256 + i),
 31		TokenID:   common.TokenID(i),
 32		Nonce:     common.Nonce(i),
 33		Balance:   big.NewInt(1000),
 34		PublicKey: pk,
 35		EthAddr:   address,
 36	}
 37}
 38
 39func TestNewStateDBIntermediateState(t *testing.T) {
 40	dir, err := ioutil.TempDir("", "tmpdb")
 41	require.Nil(t, err)
 42	defer assert.Nil(t, os.RemoveAll(dir))
 43
 44	sdb, err := NewStateDB(dir, TypeTxSelector, 0)
 45	assert.Nil(t, err)
 46
 47	// test values
 48	k0 := []byte("testkey0")
 49	k1 := []byte("testkey1")
 50	v0 := []byte("testvalue0")
 51	v1 := []byte("testvalue1")
 52
 53	// store some data
 54	tx, err := sdb.db.NewTx()
 55	assert.Nil(t, err)
 56	err = tx.Put(k0, v0)
 57	assert.Nil(t, err)
 58	err = tx.Commit()
 59	assert.Nil(t, err)
 60	v, err := sdb.db.Get(k0)
 61	assert.Nil(t, err)
 62	assert.Equal(t, v0, v)
 63
 64	// call NewStateDB which should get the db at the last checkpoint state
 65	// executing a Reset (discarding the last 'testkey0'&'testvalue0' data)
 66	sdb, err = NewStateDB(dir, TypeTxSelector, 0)
 67	assert.Nil(t, err)
 68	v, err = sdb.db.Get(k0)
 69	assert.NotNil(t, err)
 70	assert.Equal(t, db.ErrNotFound, err)
 71	assert.Nil(t, v)
 72
 73	// store the same data from the beginning that has ben lost since last NewStateDB
 74	tx, err = sdb.db.NewTx()
 75	assert.Nil(t, err)
 76	err = tx.Put(k0, v0)
 77	assert.Nil(t, err)
 78	err = tx.Commit()
 79	assert.Nil(t, err)
 80	v, err = sdb.db.Get(k0)
 81	assert.Nil(t, err)
 82	assert.Equal(t, v0, v)
 83
 84	// make checkpoints with the current state
 85	bn, err := sdb.GetCurrentBatch()
 86	assert.Nil(t, err)
 87	assert.Equal(t, common.BatchNum(0), bn)
 88	err = sdb.MakeCheckpoint()
 89	assert.Nil(t, err)
 90	bn, err = sdb.GetCurrentBatch()
 91	assert.Nil(t, err)
 92	assert.Equal(t, common.BatchNum(1), bn)
 93
 94	// write more data
 95	tx, err = sdb.db.NewTx()
 96	assert.Nil(t, err)
 97	err = tx.Put(k1, v1)
 98	assert.Nil(t, err)
 99	err = tx.Commit()
100	assert.Nil(t, err)
101
102	v, err = sdb.db.Get(k1)
103	assert.Nil(t, err)
104	assert.Equal(t, v1, v)
105
106	// call NewStateDB which should get the db at the last checkpoint state
107	// executing a Reset (discarding the last 'testkey1'&'testvalue1' data)
108	sdb, err = NewStateDB(dir, TypeTxSelector, 0)
109	assert.Nil(t, err)
110
111	v, err = sdb.db.Get(k0)
112	assert.Nil(t, err)
113	assert.Equal(t, v0, v)
114
115	v, err = sdb.db.Get(k1)
116	assert.NotNil(t, err)
117	assert.Equal(t, db.ErrNotFound, err)
118	assert.Nil(t, v)
119}
120
121func TestStateDBWithoutMT(t *testing.T) {
122	dir, err := ioutil.TempDir("", "tmpdb")
123	require.Nil(t, err)
124	defer assert.Nil(t, os.RemoveAll(dir))
125
126	sdb, err := NewStateDB(dir, TypeTxSelector, 0)
127	assert.Nil(t, err)
128
129	// create test accounts
130	var accounts []*common.Account
131	for i := 0; i < 4; i++ {
132		accounts = append(accounts, newAccount(t, i))
133	}
134
135	// get non-existing account, expecting an error
136	unexistingAccount := common.Idx(1)
137	_, err = sdb.GetAccount(unexistingAccount)
138	assert.NotNil(t, err)
139	assert.Equal(t, db.ErrNotFound, err)
140
141	// add test accounts
142	for i := 0; i < len(accounts); i++ {
143		_, err = sdb.CreateAccount(accounts[i].Idx, accounts[i])
144		assert.Nil(t, err)
145	}
146
147	for i := 0; i < len(accounts); i++ {
148		existingAccount := accounts[i].Idx
149		accGetted, err := sdb.GetAccount(existingAccount)
150		assert.Nil(t, err)
151		assert.Equal(t, accounts[i], accGetted)
152	}
153
154	// try already existing idx and get error
155	existingAccount := common.Idx(256)
156	_, err = sdb.GetAccount(existingAccount) // check that exist
157	assert.Nil(t, err)
158	_, err = sdb.CreateAccount(common.Idx(256), accounts[1]) // check that can not be created twice
159	assert.NotNil(t, err)
160	assert.Equal(t, ErrAccountAlreadyExists, err)
161
162	// update accounts
163	for i := 0; i < len(accounts); i++ {
164		accounts[i].Nonce = accounts[i].Nonce + 1
165		existingAccount = common.Idx(i)
166		_, err = sdb.UpdateAccount(existingAccount, accounts[i])
167		assert.Nil(t, err)
168	}
169
170	_, err = sdb.MTGetProof(common.Idx(1))
171	assert.NotNil(t, err)
172	assert.Equal(t, ErrStateDBWithoutMT, err)
173}
174
175func TestStateDBWithMT(t *testing.T) {
176	dir, err := ioutil.TempDir("", "tmpdb")
177	require.Nil(t, err)
178	defer assert.Nil(t, os.RemoveAll(dir))
179
180	sdb, err := NewStateDB(dir, TypeSynchronizer, 32)
181	assert.Nil(t, err)
182
183	// create test accounts
184	var accounts []*common.Account
185	for i := 0; i < 20; i++ {
186		accounts = append(accounts, newAccount(t, i))
187	}
188
189	// get non-existing account, expecting an error
190	_, err = sdb.GetAccount(common.Idx(1))
191	assert.NotNil(t, err)
192	assert.Equal(t, db.ErrNotFound, err)
193
194	// add test accounts
195	for i := 0; i < len(accounts); i++ {
196		_, err = sdb.CreateAccount(accounts[i].Idx, accounts[i])
197		assert.Nil(t, err)
198	}
199
200	for i := 0; i < len(accounts); i++ {
201		accGetted, err := sdb.GetAccount(accounts[i].Idx)
202		assert.Nil(t, err)
203		assert.Equal(t, accounts[i], accGetted)
204	}
205
206	// try already existing idx and get error
207	_, err = sdb.GetAccount(common.Idx(256)) // check that exist
208	assert.Nil(t, err)
209	_, err = sdb.CreateAccount(common.Idx(256), accounts[1]) // check that can not be created twice
210	assert.NotNil(t, err)
211	assert.Equal(t, ErrAccountAlreadyExists, err)
212
213	_, err = sdb.MTGetProof(common.Idx(256))
214	assert.Nil(t, err)
215
216	// update accounts
217	for i := 0; i < len(accounts); i++ {
218		accounts[i].Nonce = accounts[i].Nonce + 1
219		_, err = sdb.UpdateAccount(accounts[i].Idx, accounts[i])
220		assert.Nil(t, err)
221	}
222	a, err := sdb.GetAccount(common.Idx(256)) // check that account value has been updated
223	assert.Nil(t, err)
224	assert.Equal(t, accounts[0].Nonce, a.Nonce)
225}
226
227func TestCheckpoints(t *testing.T) {
228	dir, err := ioutil.TempDir("", "sdb")
229	require.Nil(t, err)
230	defer assert.Nil(t, os.RemoveAll(dir))
231
232	sdb, err := NewStateDB(dir, TypeSynchronizer, 32)
233	assert.Nil(t, err)
234
235	// create test accounts
236	var accounts []*common.Account
237	for i := 0; i < 10; i++ {
238		accounts = append(accounts, newAccount(t, i))
239	}
240
241	// add test accounts
242	for i := 0; i < len(accounts); i++ {
243		_, err = sdb.CreateAccount(accounts[i].Idx, accounts[i])
244		assert.Nil(t, err)
245	}
246
247	// do checkpoints and check that currentBatch is correct
248	err = sdb.MakeCheckpoint()
249	assert.Nil(t, err)
250	cb, err := sdb.GetCurrentBatch()
251	assert.Nil(t, err)
252	assert.Equal(t, common.BatchNum(1), cb)
253
254	for i := 1; i < 10; i++ {
255		err = sdb.MakeCheckpoint()
256		assert.Nil(t, err)
257
258		cb, err = sdb.GetCurrentBatch()
259		assert.Nil(t, err)
260		assert.Equal(t, common.BatchNum(i+1), cb)
261	}
262
263	// printCheckpoints(t, sdb.path)
264
265	// reset checkpoint
266	err = sdb.Reset(3)
267	assert.Nil(t, err)
268
269	// check that reset can be repeated (as there exist the 'current' and
270	// 'BatchNum3', from where the 'current' is a copy)
271	err = sdb.Reset(3)
272	require.Nil(t, err)
273
274	// check that currentBatch is as expected after Reset
275	cb, err = sdb.GetCurrentBatch()
276	assert.Nil(t, err)
277	assert.Equal(t, common.BatchNum(3), cb)
278
279	// advance one checkpoint and check that currentBatch is fine
280	err = sdb.MakeCheckpoint()
281	assert.Nil(t, err)
282	cb, err = sdb.GetCurrentBatch()
283	assert.Nil(t, err)
284	assert.Equal(t, common.BatchNum(4), cb)
285
286	err = sdb.DeleteCheckpoint(common.BatchNum(9))
287	assert.Nil(t, err)
288	err = sdb.DeleteCheckpoint(common.BatchNum(10))
289	assert.Nil(t, err)
290	err = sdb.DeleteCheckpoint(common.BatchNum(9)) // does not exist, should return err
291	assert.NotNil(t, err)
292	err = sdb.DeleteCheckpoint(common.BatchNum(11)) // does not exist, should return err
293	assert.NotNil(t, err)
294
295	// Create a LocalStateDB from the initial StateDB
296	dirLocal, err := ioutil.TempDir("", "ldb")
297	require.Nil(t, err)
298	defer assert.Nil(t, os.RemoveAll(dirLocal))
299	ldb, err := NewLocalStateDB(dirLocal, sdb, TypeBatchBuilder, 32)
300	assert.Nil(t, err)
301
302	// get checkpoint 4 from sdb (StateDB) to ldb (LocalStateDB)
303	err = ldb.Reset(4, true)
304	assert.Nil(t, err)
305	// check that currentBatch is 4 after the Reset
306	cb, err = ldb.GetCurrentBatch()
307	assert.Nil(t, err)
308	assert.Equal(t, common.BatchNum(4), cb)
309	// advance one checkpoint in ldb
310	err = ldb.MakeCheckpoint()
311	assert.Nil(t, err)
312	cb, err = ldb.GetCurrentBatch()
313	assert.Nil(t, err)
314	assert.Equal(t, common.BatchNum(5), cb)
315
316	// Create a 2nd LocalStateDB from the initial StateDB
317	dirLocal2, err := ioutil.TempDir("", "ldb2")
318	require.Nil(t, err)
319	defer assert.Nil(t, os.RemoveAll(dirLocal2))
320	ldb2, err := NewLocalStateDB(dirLocal2, sdb, TypeBatchBuilder, 32)
321	assert.Nil(t, err)
322
323	// get checkpoint 4 from sdb (StateDB) to ldb (LocalStateDB)
324	err = ldb2.Reset(4, true)
325	assert.Nil(t, err)
326	// check that currentBatch is 4 after the Reset
327	cb, err = ldb2.GetCurrentBatch()
328	assert.Nil(t, err)
329	assert.Equal(t, common.BatchNum(4), cb)
330	// advance one checkpoint in ldb2
331	err = ldb2.MakeCheckpoint()
332	assert.Nil(t, err)
333	cb, err = ldb2.GetCurrentBatch()
334	assert.Nil(t, err)
335	assert.Equal(t, common.BatchNum(5), cb)
336
337	debug := false
338	if debug {
339		printCheckpoints(t, sdb.path)
340		printCheckpoints(t, ldb.path)
341		printCheckpoints(t, ldb2.path)
342	}
343}
344
345func TestStateDBGetAccounts(t *testing.T) {
346	dir, err := ioutil.TempDir("", "tmpdb")
347	require.Nil(t, err)
348
349	sdb, err := NewStateDB(dir, TypeTxSelector, 0)
350	assert.Nil(t, err)
351
352	// create test accounts
353	var accounts []common.Account
354	for i := 0; i < 16; i++ {
355		account := newAccount(t, i)
356		accounts = append(accounts, *account)
357	}
358
359	// add test accounts
360	for i := range accounts {
361		_, err = sdb.CreateAccount(accounts[i].Idx, &accounts[i])
362		require.Nil(t, err)
363	}
364
365	dbAccounts, err := sdb.GetAccounts()
366	require.Nil(t, err)
367	assert.Equal(t, accounts, dbAccounts)
368}
369
370func printCheckpoints(t *testing.T, path string) {
371	files, err := ioutil.ReadDir(path)
372	assert.Nil(t, err)
373
374	fmt.Println(path)
375	for _, f := range files {
376		fmt.Println("	" + f.Name())
377	}
378}