arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/test/zkproof/zkproof_test.go
test/zkproof/zkproof_test.goRaw
  1package zkproof
  2
  3import (
  4	"context"
  5	"encoding/json"
  6	"fmt"
  7	"io/ioutil"
  8	"os"
  9	"testing"
 10	"time"
 11
 12	"github.com/hermeznetwork/hermez-node/common"
 13	"github.com/hermeznetwork/hermez-node/db/statedb"
 14	"github.com/hermeznetwork/hermez-node/prover"
 15	"github.com/hermeznetwork/hermez-node/test/til"
 16	"github.com/hermeznetwork/hermez-node/test/txsets"
 17	"github.com/hermeznetwork/hermez-node/txprocessor"
 18	"github.com/stretchr/testify/assert"
 19	"github.com/stretchr/testify/require"
 20)
 21
 22var proofServerURL string
 23
 24const pollInterval = 200 * time.Millisecond
 25
 26func TestMain(m *testing.M) {
 27	exitVal := 0
 28	proofServerURL = os.Getenv("PROOF_SERVER_URL")
 29	if proofServerURL != "" {
 30		exitVal = m.Run()
 31	}
 32	os.Exit(exitVal)
 33}
 34
 35const MaxTx = 376
 36const NLevels = 32
 37const MaxL1Tx = 256
 38const MaxFeeTx = 64
 39const ChainID uint16 = 1
 40
 41var config = txprocessor.Config{
 42	NLevels:  uint32(NLevels),
 43	MaxTx:    MaxTx,
 44	MaxL1Tx:  MaxL1Tx,
 45	MaxFeeTx: MaxFeeTx,
 46	ChainID:  ChainID,
 47}
 48
 49func initStateDB(t *testing.T) *statedb.StateDB {
 50	dir, err := ioutil.TempDir("", "tmpdb")
 51	require.NoError(t, err)
 52	defer assert.Nil(t, os.RemoveAll(dir))
 53
 54	sdb, err := statedb.NewStateDB(dir, 128, statedb.TypeBatchBuilder, NLevels)
 55	require.NoError(t, err)
 56	return sdb
 57}
 58
 59func sendProofAndCheckResp(t *testing.T, ptOut *txprocessor.ProcessTxOutput) {
 60	// Store zkinputs json for debugging purposes
 61	zkInputsJSON, err := json.Marshal(ptOut.ZKInputs)
 62	require.NoError(t, err)
 63	err = ioutil.WriteFile("/tmp/dbgZKInputs.json", zkInputsJSON, 0640) //nolint:gosec
 64	require.NoError(t, err)
 65
 66	proofServerClient := prover.NewProofServerClient(proofServerURL, pollInterval)
 67	err = proofServerClient.WaitReady(context.Background())
 68	require.NoError(t, err)
 69	err = proofServerClient.CalculateProof(context.Background(), ptOut.ZKInputs)
 70	require.NoError(t, err)
 71	proof, pubInputs, err := proofServerClient.GetProof(context.Background())
 72	require.NoError(t, err)
 73	fmt.Printf("proof: %#v\n", proof)
 74	fmt.Printf("pubInputs: %#v\n", pubInputs)
 75}
 76
 77func TestZKInputsEmpty(t *testing.T) {
 78	sdb := initStateDB(t)
 79
 80	tp := txprocessor.NewTxProcessor(sdb, config)
 81
 82	coordIdxs := []common.Idx{}
 83	l1UserTxs := []common.L1Tx{}
 84	l1CoordTxs := []common.L1Tx{}
 85	l2Txs := []common.PoolL2Tx{}
 86	ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
 87	require.NoError(t, err)
 88
 89	sendProofAndCheckResp(t, ptOut) // test empty batch ZKInputs
 90
 91	_, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs = txsets.GenerateTxsZKInputs0(t, ChainID)
 92
 93	_, err = tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
 94	require.NoError(t, err)
 95
 96	coordIdxs = []common.Idx{}
 97	l1UserTxs = []common.L1Tx{}
 98	l1CoordTxs = []common.L1Tx{}
 99	l2Txs = []common.PoolL2Tx{}
100	ptOut, err = tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
101	require.NoError(t, err)
102	sendProofAndCheckResp(t, ptOut) // test empty batch ZKInputs after a non-empty batch
103}
104
105func TestZKInputs0(t *testing.T) {
106	sdb := initStateDB(t)
107
108	_, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs := txsets.GenerateTxsZKInputs0(t, ChainID)
109
110	tp := txprocessor.NewTxProcessor(sdb, config)
111	ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
112	require.NoError(t, err)
113
114	sendProofAndCheckResp(t, ptOut)
115}
116func TestZKInputs1(t *testing.T) {
117	sdb := initStateDB(t)
118
119	_, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs := txsets.GenerateTxsZKInputs1(t, ChainID)
120
121	tp := txprocessor.NewTxProcessor(sdb, config)
122	ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
123	require.NoError(t, err)
124
125	sendProofAndCheckResp(t, ptOut)
126}
127func TestZKInputs2(t *testing.T) {
128	sdb := initStateDB(t)
129
130	_, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs := txsets.GenerateTxsZKInputs2(t, ChainID)
131
132	tp := txprocessor.NewTxProcessor(sdb, config)
133	ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
134	require.NoError(t, err)
135
136	sendProofAndCheckResp(t, ptOut)
137}
138func TestZKInputs3(t *testing.T) {
139	sdb := initStateDB(t)
140
141	_, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs := txsets.GenerateTxsZKInputs3(t, ChainID)
142
143	tp := txprocessor.NewTxProcessor(sdb, config)
144	ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
145	require.NoError(t, err)
146
147	sendProofAndCheckResp(t, ptOut)
148}
149func TestZKInputs4(t *testing.T) {
150	sdb := initStateDB(t)
151
152	_, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs := txsets.GenerateTxsZKInputs4(t, ChainID)
153
154	tp := txprocessor.NewTxProcessor(sdb, config)
155	ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
156	require.NoError(t, err)
157
158	sendProofAndCheckResp(t, ptOut)
159}
160
161func TestZKInputs5(t *testing.T) {
162	sdb := initStateDB(t)
163
164	_, coordIdxs, l1UserTxs, l1CoordTxs, l2Txs := txsets.GenerateTxsZKInputs5(t, ChainID)
165
166	tp := txprocessor.NewTxProcessor(sdb, config)
167	ptOut, err := tp.ProcessTxs(coordIdxs, l1UserTxs, l1CoordTxs, l2Txs)
168	require.NoError(t, err)
169
170	sendProofAndCheckResp(t, ptOut)
171}
172
173func TestZKInputs6(t *testing.T) {
174	sdb := initStateDB(t)
175
176	tc := til.NewContext(ChainID, common.RollupConstMaxL1UserTx)
177	blocks, err := tc.GenerateBlocks(txsets.SetBlockchainMinimumFlow0)
178	require.NoError(t, err)
179
180	// restart nonces of TilContext, as will be set by generating directly
181	// the PoolL2Txs for each specific batch with tc.GeneratePoolL2Txs
182	tc.RestartNonces()
183
184	tp := txprocessor.NewTxProcessor(sdb, config)
185	// batch1
186	ptOut, err := tp.ProcessTxs(nil, nil, blocks[0].Rollup.Batches[0].L1CoordinatorTxs, nil)
187	require.NoError(t, err)
188
189	sendProofAndCheckResp(t, ptOut)
190
191	// batch2
192	l1UserTxs := []common.L1Tx{}
193	l2Txs := common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[1].L2Txs)
194	ptOut, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
195	require.NoError(t, err)
196
197	sendProofAndCheckResp(t, ptOut)
198
199	// batch3
200	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[2].Batch.ForgeL1TxsNum])
201	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[2].L2Txs)
202	ptOut, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[2].L1CoordinatorTxs, l2Txs)
203	require.NoError(t, err)
204
205	sendProofAndCheckResp(t, ptOut)
206
207	// batch4
208	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[3].Batch.ForgeL1TxsNum])
209	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[3].L2Txs)
210	ptOut, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[3].L1CoordinatorTxs, l2Txs)
211	require.NoError(t, err)
212
213	sendProofAndCheckResp(t, ptOut)
214
215	// batch5
216	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[4].Batch.ForgeL1TxsNum])
217	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[4].L2Txs)
218	ptOut, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[4].L1CoordinatorTxs, l2Txs)
219	require.NoError(t, err)
220
221	sendProofAndCheckResp(t, ptOut)
222
223	// batch6
224	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[5].Batch.ForgeL1TxsNum])
225	l2Txs = common.L2TxsToPoolL2Txs(blocks[0].Rollup.Batches[5].L2Txs)
226	ptOut, err = tp.ProcessTxs(nil, l1UserTxs, blocks[0].Rollup.Batches[5].L1CoordinatorTxs, l2Txs)
227	require.NoError(t, err)
228
229	sendProofAndCheckResp(t, ptOut)
230
231	// batch7
232	// simulate the PoolL2Txs of the batch6
233	batchPoolL2 := `
234	Type: PoolL2
235	PoolTransferToEthAddr(1) A-B: 200 (126)
236	PoolTransferToEthAddr(0) B-C: 100 (126)`
237	poolL2Txs, err := tc.GeneratePoolL2Txs(batchPoolL2)
238	require.NoError(t, err)
239
240	// Coordinator Idx where to send the fees
241	coordIdxs := []common.Idx{261, 262}
242	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[6].Batch.ForgeL1TxsNum])
243	l2Txs = poolL2Txs
244	ptOut, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Rollup.Batches[6].L1CoordinatorTxs, l2Txs)
245	require.NoError(t, err)
246
247	sendProofAndCheckResp(t, ptOut)
248
249	// batch8
250	// simulate the PoolL2Txs of the batch7
251	batchPoolL2 = `
252	Type: PoolL2
253	PoolTransfer(0) A-B: 100 (126)
254	PoolTransfer(0) C-A: 50 (126)
255	PoolTransfer(1) B-C: 100 (126)
256	PoolExit(0) A: 100 (126)`
257	poolL2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2)
258	require.NoError(t, err)
259
260	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[0].Rollup.Batches[7].Batch.ForgeL1TxsNum])
261	l2Txs = poolL2Txs
262	ptOut, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[0].Rollup.Batches[7].L1CoordinatorTxs, l2Txs)
263	require.NoError(t, err)
264
265	sendProofAndCheckResp(t, ptOut)
266
267	// batch9
268	// simulate the PoolL2Txs of the batch9
269	batchPoolL2 = `
270	Type: PoolL2
271	PoolTransfer(0) D-A: 300 (126)
272	PoolTransfer(0) B-D: 100 (126)`
273	poolL2Txs, err = tc.GeneratePoolL2Txs(batchPoolL2)
274	require.NoError(t, err)
275
276	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[0].Batch.ForgeL1TxsNum])
277	l2Txs = poolL2Txs
278	coordIdxs = []common.Idx{262}
279	ptOut, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[1].Rollup.Batches[0].L1CoordinatorTxs, l2Txs)
280	require.NoError(t, err)
281
282	sendProofAndCheckResp(t, ptOut)
283
284	// batch10
285	l1UserTxs = til.L1TxsToCommonL1Txs(tc.Queues[*blocks[1].Rollup.Batches[1].Batch.ForgeL1TxsNum])
286	l2Txs = []common.PoolL2Tx{}
287	coordIdxs = []common.Idx{}
288	ptOut, err = tp.ProcessTxs(coordIdxs, l1UserTxs, blocks[1].Rollup.Batches[1].L1CoordinatorTxs, l2Txs)
289	require.NoError(t, err)
290
291	sendProofAndCheckResp(t, ptOut)
292}