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