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