github.com/0xPolygon/supernets2-node@v0.0.0-20230711153321-2fe574524eaa/synchronizer/datacommittee_test.go (about) 1 package synchronizer 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "math/big" 8 "strconv" 9 "testing" 10 11 "github.com/0xPolygon/supernets2-node/etherman" 12 "github.com/0xPolygon/supernets2-node/jsonrpc/types" 13 "github.com/0xPolygon/supernets2-node/state" 14 "github.com/ethereum/go-ethereum/common" 15 ethTypes "github.com/ethereum/go-ethereum/core/types" 16 "github.com/ethereum/go-ethereum/crypto" 17 "github.com/stretchr/testify/assert" 18 "github.com/stretchr/testify/require" 19 ) 20 21 func TestGetBatchL2DataWithoutCommittee(t *testing.T) { 22 m := mocks{ 23 State: newStateMock(t), 24 ZKEVMClient: newZkEVMClientMock(t), 25 Etherman: newEthermanMock(t), 26 } 27 28 ctx := context.Background() 29 30 trustedSync := ClientSynchronizer{ 31 isTrustedSequencer: true, 32 state: m.State, 33 zkEVMClient: m.ZKEVMClient, 34 etherMan: m.Etherman, 35 ctx: ctx, 36 selectedCommitteeMember: -1, 37 } 38 39 permissionlessSync := ClientSynchronizer{ 40 isTrustedSequencer: false, 41 state: m.State, 42 zkEVMClient: m.ZKEVMClient, 43 etherMan: m.Etherman, 44 ctx: ctx, 45 selectedCommitteeMember: -1, 46 } 47 48 const batchNum uint64 = 5 49 batchNumBig := big.NewInt(int64(batchNum)) 50 dataFromDB := []byte("i poli tis Kerkyras einai omorfi") 51 errorHash := state.ZeroHash 52 unexpectedErrFromDB := errors.New("unexpected db") 53 errFromDBTemplate := "failed to get batch data from state for batch num " + strconv.Itoa(int(batchNum)) + ": %s" 54 55 trustedResponse := &types.Batch{Transactions: []types.TransactionOrHash{ 56 {Tx: &types.Transaction{Nonce: 4}}, 57 {Tx: &types.Transaction{Nonce: 284}}, 58 }} 59 txs := []ethTypes.Transaction{} 60 for _, transaction := range trustedResponse.Transactions { 61 tx := transaction.Tx.CoreTx() 62 txs = append(txs, *tx) 63 } 64 dataFromTrusted, err := state.EncodeTransactions(txs) 65 require.NoError(t, err) 66 trustedResponse.BatchL2Data = dataFromTrusted 67 trustedResponseEmpty := &types.Batch{Transactions: []types.TransactionOrHash{}} 68 txs = []ethTypes.Transaction{} 69 dataFromTrustedEmpty, err := state.EncodeTransactions(txs) 70 require.NoError(t, err) 71 72 unexpectedErrFromTrusted := errors.New("unexpected trusted") 73 74 type testCase struct { 75 Name string 76 ExpectedResult []byte 77 ExpectedError error 78 Sync *ClientSynchronizer 79 SetupMocks func(m *mocks) 80 } 81 82 testCases := []testCase{ 83 // Trusted sync cases 84 { 85 Name: "Trusted sync fail if unexpected error from DB", 86 ExpectedResult: nil, 87 ExpectedError: fmt.Errorf(errFromDBTemplate, unexpectedErrFromDB), 88 Sync: &trustedSync, 89 SetupMocks: func(m *mocks) { 90 m.State. 91 On("GetBatchL2DataByNumber", ctx, batchNum, nil). 92 Return(nil, unexpectedErrFromDB). 93 Once() 94 }, 95 }, 96 { 97 Name: "Trusted sync fail if data not found on DB", 98 ExpectedResult: nil, 99 ExpectedError: fmt.Errorf("data not found on the local DB nor on any data committee member"), 100 Sync: &trustedSync, 101 SetupMocks: func(m *mocks) { 102 m.State. 103 On("GetBatchL2DataByNumber", ctx, batchNum, nil). 104 Return(nil, state.ErrNotFound). 105 Once() 106 m.Etherman. 107 On("GetCurrentDataCommittee"). 108 Return(nil, nil). 109 Once() 110 }, 111 }, 112 { 113 Name: "Trusted sync fail if hash missmatch on DB", 114 ExpectedResult: nil, 115 ExpectedError: fmt.Errorf("data not found on the local DB nor on any data committee member"), 116 Sync: &trustedSync, 117 SetupMocks: func(m *mocks) { 118 m.State. 119 On("GetBatchL2DataByNumber", ctx, batchNum, nil). 120 Return(dataFromDB, nil). 121 Once() 122 m.Etherman. 123 On("GetCurrentDataCommittee"). 124 Return(nil, nil). 125 Once() 126 }, 127 }, 128 { 129 Name: "Trusted sync succeeds if hash match on DB", 130 ExpectedResult: dataFromDB, 131 ExpectedError: nil, 132 Sync: &trustedSync, 133 SetupMocks: func(m *mocks) { 134 m.State. 135 On("GetBatchL2DataByNumber", ctx, batchNum, nil). 136 Return(dataFromDB, nil). 137 Once() 138 }, 139 }, 140 // Permissionless sync cases 141 { 142 Name: "Permissionless sync succeeds if hash match on DB", 143 ExpectedResult: dataFromDB, 144 ExpectedError: nil, 145 Sync: &permissionlessSync, 146 SetupMocks: func(m *mocks) { 147 m.State. 148 On("GetBatchL2DataByNumber", ctx, batchNum, nil). 149 Return(dataFromDB, nil). 150 Once() 151 }, 152 }, 153 { 154 Name: "Permissionless sync fail if unexpected error from DB", 155 ExpectedResult: nil, 156 ExpectedError: fmt.Errorf(errFromDBTemplate, unexpectedErrFromDB), 157 Sync: &permissionlessSync, 158 SetupMocks: func(m *mocks) { 159 m.State. 160 On("GetBatchL2DataByNumber", ctx, batchNum, nil). 161 Return(nil, unexpectedErrFromDB). 162 Once() 163 }, 164 }, 165 { 166 Name: "Permissionless sync fail if hash missmatch on the DB and error from trusted", 167 ExpectedResult: nil, 168 ExpectedError: fmt.Errorf("data not found on the local DB, nor from the trusted sequencer nor on any data committee member"), 169 Sync: &permissionlessSync, 170 SetupMocks: func(m *mocks) { 171 m.State. 172 On("GetBatchL2DataByNumber", ctx, batchNum, nil). 173 Return(dataFromDB, nil). 174 Once() 175 m.Etherman. 176 On("GetCurrentDataCommittee"). 177 Return(nil, nil). 178 Once() 179 m.ZKEVMClient. 180 On("BatchByNumber", ctx, batchNumBig). 181 Return(nil, unexpectedErrFromTrusted). 182 Once() 183 }, 184 }, 185 { 186 Name: "Permissionless sync fail if hash missmatch on the DB and from trusted sequencer", 187 ExpectedResult: nil, 188 ExpectedError: fmt.Errorf("data not found on the local DB, nor from the trusted sequencer nor on any data committee member"), 189 Sync: &permissionlessSync, 190 SetupMocks: func(m *mocks) { 191 m.State. 192 On("GetBatchL2DataByNumber", ctx, batchNum, nil). 193 Return(dataFromDB, nil). 194 Once() 195 m.Etherman. 196 On("GetCurrentDataCommittee"). 197 Return(nil, nil). 198 Once() 199 m.ZKEVMClient. 200 On("BatchByNumber", ctx, batchNumBig). 201 Return(trustedResponse, nil). 202 Once() 203 }, 204 }, 205 { 206 Name: "Permissionless sync succeeds if hash missmatch on the DB and match from trusted", 207 ExpectedResult: dataFromTrusted, 208 ExpectedError: nil, 209 Sync: &permissionlessSync, 210 SetupMocks: func(m *mocks) { 211 m.State. 212 On("GetBatchL2DataByNumber", ctx, batchNum, nil). 213 Return(dataFromDB, nil). 214 Once() 215 m.ZKEVMClient. 216 On("BatchByNumber", ctx, batchNumBig). 217 Return(trustedResponse, nil). 218 Once() 219 }, 220 }, 221 { 222 Name: "Permissionless sync fail if not found on the DB and error from trusted", 223 ExpectedResult: nil, 224 ExpectedError: fmt.Errorf("data not found on the local DB, nor from the trusted sequencer nor on any data committee member"), 225 Sync: &permissionlessSync, 226 SetupMocks: func(m *mocks) { 227 m.State. 228 On("GetBatchL2DataByNumber", ctx, batchNum, nil). 229 Return(nil, state.ErrNotFound). 230 Once() 231 m.Etherman. 232 On("GetCurrentDataCommittee"). 233 Return(nil, nil). 234 Once() 235 m.ZKEVMClient. 236 On("BatchByNumber", ctx, batchNumBig). 237 Return(nil, unexpectedErrFromTrusted). 238 Once() 239 }, 240 }, 241 { 242 Name: "Permissionless sync fail fail if not found on the DB and hash missmatch trusted", 243 ExpectedResult: nil, 244 ExpectedError: fmt.Errorf("data not found on the local DB, nor from the trusted sequencer nor on any data committee member"), 245 Sync: &permissionlessSync, 246 SetupMocks: func(m *mocks) { 247 m.State. 248 On("GetBatchL2DataByNumber", ctx, batchNum, nil). 249 Return(nil, state.ErrNotFound). 250 Once() 251 m.Etherman. 252 On("GetCurrentDataCommittee"). 253 Return(nil, nil). 254 Once() 255 m.ZKEVMClient. 256 On("BatchByNumber", ctx, batchNumBig). 257 Return(trustedResponse, nil). 258 Once() 259 }, 260 }, 261 { 262 Name: "Permissionless sync succeeds if not found on the DB and match from trusted", 263 ExpectedResult: dataFromTrusted, 264 ExpectedError: nil, 265 Sync: &permissionlessSync, 266 SetupMocks: func(m *mocks) { 267 m.State. 268 On("GetBatchL2DataByNumber", ctx, batchNum, nil). 269 Return(nil, state.ErrNotFound). 270 Once() 271 m.ZKEVMClient. 272 On("BatchByNumber", ctx, batchNumBig). 273 Return(trustedResponse, nil). 274 Once() 275 }, 276 }, 277 { 278 Name: "Permissionless sync succeeds if not found on the DB and match from trusted empty response", 279 ExpectedResult: dataFromTrustedEmpty, 280 ExpectedError: nil, 281 Sync: &permissionlessSync, 282 SetupMocks: func(m *mocks) { 283 m.State. 284 On("GetBatchL2DataByNumber", ctx, batchNum, nil). 285 Return(nil, state.ErrNotFound). 286 Once() 287 m.ZKEVMClient. 288 On("BatchByNumber", ctx, batchNumBig). 289 Return(trustedResponseEmpty, nil). 290 Once() 291 }, 292 }, 293 } 294 295 for _, testCase := range testCases { 296 t.Run(testCase.Name, func(t *testing.T) { 297 tc := testCase 298 tc.SetupMocks(&m) 299 300 var expectedHash common.Hash 301 if tc.ExpectedError == nil { 302 expectedHash = crypto.Keccak256Hash(tc.ExpectedResult) 303 } else { 304 expectedHash = errorHash 305 } 306 307 res, err := tc.Sync.getBatchL2Data(batchNum, expectedHash) 308 assert.Equal(t, tc.ExpectedResult, res) 309 if tc.ExpectedError != nil { 310 require.NotNil(t, err) 311 assert.Equal(t, tc.ExpectedError.Error(), err.Error()) 312 } 313 }) 314 } 315 } 316 317 func TestGetBatchL2DataWithCommittee(t *testing.T) { 318 m := mocks{ 319 State: newStateMock(t), 320 ZKEVMClient: newZkEVMClientMock(t), 321 Etherman: newEthermanMock(t), 322 DataCommitteeClientFactory: newDataCommitteeClientFactoryMock(t), 323 } 324 325 ctx := context.Background() 326 327 committeeMembers := []etherman.DataCommitteeMember{ 328 { 329 URL: "0", 330 Addr: common.HexToAddress("0x0"), 331 }, 332 { 333 URL: "1", 334 Addr: common.HexToAddress("0x1"), 335 }, 336 { 337 URL: "2", 338 Addr: common.HexToAddress("0x2"), 339 }, 340 } 341 trustedSync := ClientSynchronizer{ 342 isTrustedSequencer: true, 343 state: m.State, 344 zkEVMClient: m.ZKEVMClient, 345 etherMan: m.Etherman, 346 ctx: ctx, 347 selectedCommitteeMember: 0, 348 committeeMembers: committeeMembers, 349 dataCommitteeClientFactory: m.DataCommitteeClientFactory, 350 } 351 352 permissionlessSync := ClientSynchronizer{ 353 isTrustedSequencer: false, 354 state: m.State, 355 zkEVMClient: m.ZKEVMClient, 356 etherMan: m.Etherman, 357 ctx: ctx, 358 selectedCommitteeMember: 1, 359 committeeMembers: committeeMembers, 360 dataCommitteeClientFactory: m.DataCommitteeClientFactory, 361 } 362 363 const batchNum uint64 = 5 364 batchNumBig := big.NewInt(int64(batchNum)) 365 dataFromDB := []byte("i poli tis Kerkyras einai omorfi") 366 errorHash := state.ZeroHash 367 368 trustedResponse := &types.Batch{Transactions: []types.TransactionOrHash{ 369 {Tx: &types.Transaction{Nonce: 4}}, 370 {Tx: &types.Transaction{Nonce: 284}}, 371 }} 372 txs := []ethTypes.Transaction{} 373 for _, transaction := range trustedResponse.Transactions { 374 tx := transaction.Tx.CoreTx() 375 txs = append(txs, *tx) 376 } 377 dataFromTrusted, err := state.EncodeTransactions(txs) 378 require.NoError(t, err) 379 trustedResponse.BatchL2Data = dataFromTrusted 380 381 type testCase struct { 382 Name string 383 ExpectedResult []byte 384 ExpectedError error 385 Sync *ClientSynchronizer 386 SetupMocks func(m *mocks) 387 Retry bool 388 } 389 390 testCases := []testCase{ 391 // Trusted sync cases 392 { 393 Name: "Trusted sync fail if all the members don't answer", 394 ExpectedResult: nil, 395 ExpectedError: fmt.Errorf("data not found on the local DB nor on any data committee member"), 396 Sync: &trustedSync, 397 SetupMocks: func(m *mocks) { 398 m.State. 399 On("GetBatchL2DataByNumber", ctx, batchNum, nil). 400 Return(nil, state.ErrNotFound). 401 Once() 402 DAClientMock := newDataCommitteeClientMock(t) 403 m.DataCommitteeClientFactory. 404 On("New", "0"). 405 Return(DAClientMock). 406 Once() 407 DAClientMock. 408 On("GetOffChainData", trustedSync.ctx, state.ZeroHash). 409 Return([]byte("not the correct data"), nil). 410 Once() 411 m.DataCommitteeClientFactory. 412 On("New", "1"). 413 Return(DAClientMock). 414 Once() 415 DAClientMock. 416 On("GetOffChainData", trustedSync.ctx, state.ZeroHash). 417 Return(nil, errors.New("not today")). 418 Once() 419 m.DataCommitteeClientFactory. 420 On("New", "2"). 421 Return(DAClientMock). 422 Once() 423 DAClientMock. 424 On("GetOffChainData", trustedSync.ctx, state.ZeroHash). 425 Return([]byte("not the correct data"), nil). 426 Once() 427 m.Etherman. 428 On("GetCurrentDataCommittee"). 429 Return(nil, nil). 430 Once() 431 }, 432 }, 433 { 434 Name: "Trusted sync succeeds after 2nd committee member answers correctly", 435 ExpectedResult: dataFromDB, 436 ExpectedError: nil, 437 Sync: &trustedSync, 438 SetupMocks: func(m *mocks) { 439 // Reset DAC 440 trustedSync.committeeMembers = committeeMembers 441 trustedSync.selectedCommitteeMember = 0 442 m.State. 443 On("GetBatchL2DataByNumber", ctx, batchNum, nil). 444 Return(nil, state.ErrNotFound). 445 Once() 446 DAClientMock := newDataCommitteeClientMock(t) 447 m.DataCommitteeClientFactory. 448 On("New", "0"). 449 Return(DAClientMock). 450 Once() 451 DAClientMock. 452 On("GetOffChainData", trustedSync.ctx, crypto.Keccak256Hash(dataFromDB)). 453 Return([]byte("not the correct data"), nil). 454 Once() 455 m.DataCommitteeClientFactory. 456 On("New", "1"). 457 Return(DAClientMock). 458 Once() 459 DAClientMock. 460 On("GetOffChainData", trustedSync.ctx, crypto.Keccak256Hash(dataFromDB)). 461 Return(nil, errors.New("not today")). 462 Once() 463 m.DataCommitteeClientFactory. 464 On("New", "2"). 465 Return(DAClientMock). 466 Once() 467 DAClientMock. 468 On("GetOffChainData", trustedSync.ctx, crypto.Keccak256Hash(dataFromDB)). 469 Return(dataFromDB, nil). 470 Once() 471 }, 472 }, 473 // Permissionless sync cases 474 { 475 Name: "Permissionless sync succeeds after 2nd committee member answers correctly", 476 ExpectedResult: dataFromDB, 477 ExpectedError: nil, 478 Sync: &permissionlessSync, 479 SetupMocks: func(m *mocks) { 480 m.State. 481 On("GetBatchL2DataByNumber", ctx, batchNum, nil). 482 Return(nil, state.ErrNotFound). 483 Once() 484 m.ZKEVMClient. 485 On("BatchByNumber", ctx, batchNumBig). 486 Return(nil, errors.New("not today")). 487 Once() 488 DAClientMock := newDataCommitteeClientMock(t) 489 m.DataCommitteeClientFactory. 490 On("New", "1"). 491 Return(DAClientMock). 492 Once() 493 DAClientMock. 494 On("GetOffChainData", trustedSync.ctx, crypto.Keccak256Hash(dataFromDB)). 495 Return([]byte("not the correct data"), nil). 496 Once() 497 m.DataCommitteeClientFactory. 498 On("New", "2"). 499 Return(DAClientMock). 500 Once() 501 DAClientMock. 502 On("GetOffChainData", trustedSync.ctx, crypto.Keccak256Hash(dataFromDB)). 503 Return(nil, errors.New("not today")). 504 Once() 505 m.DataCommitteeClientFactory. 506 On("New", "0"). 507 Return(DAClientMock). 508 Once() 509 DAClientMock. 510 On("GetOffChainData", trustedSync.ctx, crypto.Keccak256Hash(dataFromDB)). 511 Return(dataFromDB, nil). 512 Once() 513 }, 514 }, 515 { 516 Name: "Permissionless sync succeeds after updating DAC", 517 ExpectedResult: dataFromDB, 518 ExpectedError: nil, 519 Sync: &permissionlessSync, 520 Retry: true, 521 SetupMocks: func(m *mocks) { 522 m.State. 523 On("GetBatchL2DataByNumber", ctx, batchNum, nil). 524 Return(nil, state.ErrNotFound). 525 Once() 526 m.ZKEVMClient. 527 On("BatchByNumber", ctx, batchNumBig). 528 Return(nil, errors.New("not today")). 529 Once() 530 DAClientMock := newDataCommitteeClientMock(t) 531 m.DataCommitteeClientFactory. 532 On("New", "1"). 533 Return(DAClientMock). 534 Once() 535 DAClientMock. 536 On("GetOffChainData", trustedSync.ctx, crypto.Keccak256Hash(dataFromDB)). 537 Return([]byte("not the correct data"), nil). 538 Once() 539 m.DataCommitteeClientFactory. 540 On("New", "2"). 541 Return(DAClientMock). 542 Once() 543 DAClientMock. 544 On("GetOffChainData", trustedSync.ctx, crypto.Keccak256Hash(dataFromDB)). 545 Return(nil, errors.New("not today")). 546 Once() 547 m.DataCommitteeClientFactory. 548 On("New", "0"). 549 Return(DAClientMock). 550 Once() 551 DAClientMock. 552 On("GetOffChainData", trustedSync.ctx, crypto.Keccak256Hash(dataFromDB)). 553 Return(nil, errors.New("not today")). 554 Once() 555 const succesfullURL = "the time is now" 556 m.Etherman. 557 On("GetCurrentDataCommittee"). 558 Return(ðerman.DataCommittee{ 559 Members: []etherman.DataCommitteeMember{{ 560 URL: succesfullURL, 561 Addr: common.HexToAddress("0xff"), 562 }}, 563 }, nil). 564 Once() 565 m.State. 566 On("GetBatchL2DataByNumber", ctx, batchNum, nil). 567 Return(nil, state.ErrNotFound). 568 Once() 569 m.ZKEVMClient. 570 On("BatchByNumber", ctx, batchNumBig). 571 Return(nil, errors.New("not today")). 572 Once() 573 m.DataCommitteeClientFactory. 574 On("New", succesfullURL). 575 Return(DAClientMock). 576 Once() 577 DAClientMock. 578 On("GetOffChainData", trustedSync.ctx, crypto.Keccak256Hash(dataFromDB)). 579 Return(dataFromDB, nil). 580 Once() 581 }, 582 }, 583 } 584 585 for _, testCase := range testCases { 586 t.Run(testCase.Name, func(t *testing.T) { 587 tc := testCase 588 tc.SetupMocks(&m) 589 590 var expectedHash common.Hash 591 if tc.ExpectedError == nil { 592 expectedHash = crypto.Keccak256Hash(tc.ExpectedResult) 593 } else { 594 expectedHash = errorHash 595 } 596 597 res, err := tc.Sync.getBatchL2Data(batchNum, expectedHash) 598 if tc.Retry { 599 require.Error(t, err) 600 res, err = tc.Sync.getBatchL2Data(batchNum, expectedHash) 601 } 602 assert.Equal(t, tc.ExpectedResult, res) 603 if tc.ExpectedError != nil { 604 require.NotNil(t, err) 605 assert.Equal(t, tc.ExpectedError.Error(), err.Error()) 606 } 607 }) 608 } 609 }