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