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 TestStateDBWithoutMT(t *testing.T) {
 38	dir, err := ioutil.TempDir("", "tmpdb")
 39	require.Nil(t, err)
 40
 41	sdb, err := NewStateDB(dir, false, 0)
 42	assert.Nil(t, err)
 43
 44	// create test accounts
 45	var accounts []*common.Account
 46	for i := 0; i < 100; i++ {
 47		accounts = append(accounts, newAccount(t, i))
 48	}
 49
 50	// get non-existing account, expecting an error
 51	_, err = sdb.GetAccount(common.Idx(1))
 52	assert.NotNil(t, err)
 53	assert.Equal(t, db.ErrNotFound, err)
 54
 55	// add test accounts
 56	for i := 0; i < len(accounts); i++ {
 57		_, err = sdb.CreateAccount(common.Idx(i), accounts[i])
 58		assert.Nil(t, err)
 59	}
 60
 61	for i := 0; i < len(accounts); i++ {
 62		accGetted, err := sdb.GetAccount(common.Idx(i))
 63		assert.Nil(t, err)
 64		assert.Equal(t, accounts[i], accGetted)
 65	}
 66
 67	// try already existing idx and get error
 68	_, err = sdb.GetAccount(common.Idx(1)) // check that exist
 69	assert.Nil(t, err)
 70	_, err = sdb.CreateAccount(common.Idx(1), accounts[1]) // check that can not be created twice
 71	assert.NotNil(t, err)
 72	assert.Equal(t, ErrAccountAlreadyExists, err)
 73
 74	// update accounts
 75	for i := 0; i < len(accounts); i++ {
 76		accounts[i].Nonce = accounts[i].Nonce + 1
 77		_, err = sdb.UpdateAccount(common.Idx(i), accounts[i])
 78		assert.Nil(t, err)
 79	}
 80
 81	_, err = sdb.MTGetProof(common.Idx(1))
 82	assert.NotNil(t, err)
 83	assert.Equal(t, ErrStateDBWithoutMT, err)
 84}
 85
 86func TestStateDBWithMT(t *testing.T) {
 87	dir, err := ioutil.TempDir("", "tmpdb")
 88	require.Nil(t, err)
 89
 90	sdb, err := NewStateDB(dir, true, 32)
 91	assert.Nil(t, err)
 92
 93	// create test accounts
 94	var accounts []*common.Account
 95	for i := 0; i < 20; i++ {
 96		accounts = append(accounts, newAccount(t, i))
 97	}
 98
 99	// get non-existing account, expecting an error
100	_, err = sdb.GetAccount(common.Idx(1))
101	assert.NotNil(t, err)
102	assert.Equal(t, db.ErrNotFound, err)
103
104	// add test accounts
105	for i := 0; i < len(accounts); i++ {
106		_, err = sdb.CreateAccount(common.Idx(i), accounts[i])
107		assert.Nil(t, err)
108	}
109
110	for i := 0; i < len(accounts); i++ {
111		accGetted, err := sdb.GetAccount(common.Idx(i))
112		assert.Nil(t, err)
113		assert.Equal(t, accounts[i], accGetted)
114	}
115
116	// try already existing idx and get error
117	_, err = sdb.GetAccount(common.Idx(1)) // check that exist
118	assert.Nil(t, err)
119	_, err = sdb.CreateAccount(common.Idx(1), accounts[1]) // check that can not be created twice
120	assert.NotNil(t, err)
121	assert.Equal(t, ErrAccountAlreadyExists, err)
122
123	_, err = sdb.MTGetProof(common.Idx(1))
124	assert.Nil(t, err)
125
126	// update accounts
127	for i := 0; i < len(accounts); i++ {
128		accounts[i].Nonce = accounts[i].Nonce + 1
129		_, err = sdb.UpdateAccount(common.Idx(i), accounts[i])
130		assert.Nil(t, err)
131	}
132	a, err := sdb.GetAccount(common.Idx(1)) // check that account value has been updated
133	assert.Nil(t, err)
134	assert.Equal(t, accounts[1].Nonce, a.Nonce)
135}
136
137func TestCheckpoints(t *testing.T) {
138	dir, err := ioutil.TempDir("", "sdb")
139	require.Nil(t, err)
140
141	sdb, err := NewStateDB(dir, true, 32)
142	assert.Nil(t, err)
143
144	// create test accounts
145	var accounts []*common.Account
146	for i := 0; i < 10; i++ {
147		accounts = append(accounts, newAccount(t, i))
148	}
149
150	// add test accounts
151	for i := 0; i < len(accounts); i++ {
152		_, err = sdb.CreateAccount(common.Idx(i), accounts[i])
153		assert.Nil(t, err)
154	}
155
156	// do checkpoints and check that currentBatch is correct
157	err = sdb.MakeCheckpoint()
158	assert.Nil(t, err)
159	cb, err := sdb.GetCurrentBatch()
160	assert.Nil(t, err)
161	assert.Equal(t, common.BatchNum(1), cb)
162
163	for i := 1; i < 10; i++ {
164		err = sdb.MakeCheckpoint()
165		assert.Nil(t, err)
166
167		cb, err = sdb.GetCurrentBatch()
168		assert.Nil(t, err)
169		assert.Equal(t, common.BatchNum(i+1), cb)
170	}
171
172	// printCheckpoints(t, sdb.path)
173
174	// reset checkpoint
175	err = sdb.Reset(3)
176	assert.Nil(t, err)
177
178	// check that reset can be repeated (as there exist the 'current' and
179	// 'BatchNum3', from where the 'current' is a copy)
180	err = sdb.Reset(3)
181	require.Nil(t, err)
182
183	// check that currentBatch is as expected after Reset
184	cb, err = sdb.GetCurrentBatch()
185	assert.Nil(t, err)
186	assert.Equal(t, common.BatchNum(3), cb)
187
188	// advance one checkpoint and check that currentBatch is fine
189	err = sdb.MakeCheckpoint()
190	assert.Nil(t, err)
191	cb, err = sdb.GetCurrentBatch()
192	assert.Nil(t, err)
193	assert.Equal(t, common.BatchNum(4), cb)
194
195	err = sdb.DeleteCheckpoint(common.BatchNum(9))
196	assert.Nil(t, err)
197	err = sdb.DeleteCheckpoint(common.BatchNum(10))
198	assert.Nil(t, err)
199	err = sdb.DeleteCheckpoint(common.BatchNum(9)) // does not exist, should return err
200	assert.NotNil(t, err)
201	err = sdb.DeleteCheckpoint(common.BatchNum(11)) // does not exist, should return err
202	assert.NotNil(t, err)
203
204	// Create a LocalStateDB from the initial StateDB
205	dirLocal, err := ioutil.TempDir("", "ldb")
206	require.Nil(t, err)
207	ldb, err := NewLocalStateDB(dirLocal, sdb, true, 32)
208	assert.Nil(t, err)
209
210	// get checkpoint 4 from sdb (StateDB) to ldb (LocalStateDB)
211	err = ldb.Reset(4, true)
212	assert.Nil(t, err)
213	// check that currentBatch is 4 after the Reset
214	cb, err = ldb.GetCurrentBatch()
215	assert.Nil(t, err)
216	assert.Equal(t, common.BatchNum(4), cb)
217	// advance one checkpoint in ldb
218	err = ldb.MakeCheckpoint()
219	assert.Nil(t, err)
220	cb, err = ldb.GetCurrentBatch()
221	assert.Nil(t, err)
222	assert.Equal(t, common.BatchNum(5), cb)
223
224	// Create a 2nd LocalStateDB from the initial StateDB
225	dirLocal2, err := ioutil.TempDir("", "ldb2")
226	require.Nil(t, err)
227	ldb2, err := NewLocalStateDB(dirLocal2, sdb, true, 32)
228	assert.Nil(t, err)
229
230	// get checkpoint 4 from sdb (StateDB) to ldb (LocalStateDB)
231	err = ldb2.Reset(4, true)
232	assert.Nil(t, err)
233	// check that currentBatch is 4 after the Reset
234	cb, err = ldb2.GetCurrentBatch()
235	assert.Nil(t, err)
236	assert.Equal(t, common.BatchNum(4), cb)
237	// advance one checkpoint in ldb2
238	err = ldb2.MakeCheckpoint()
239	assert.Nil(t, err)
240	cb, err = ldb2.GetCurrentBatch()
241	assert.Nil(t, err)
242	assert.Equal(t, common.BatchNum(5), cb)
243
244	debug := false
245	if debug {
246		printCheckpoints(t, sdb.path)
247		printCheckpoints(t, ldb.path)
248		printCheckpoints(t, ldb2.path)
249	}
250}
251
252func printCheckpoints(t *testing.T, path string) {
253	files, err := ioutil.ReadDir(path)
254	assert.Nil(t, err)
255
256	fmt.Println(path)
257	for _, f := range files {
258		fmt.Println("	" + f.Name())
259	}
260}