You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

627 lines
19 KiB

  1. package evidence_test
  2. import (
  3. "context"
  4. "testing"
  5. "time"
  6. "github.com/stretchr/testify/assert"
  7. "github.com/stretchr/testify/mock"
  8. "github.com/stretchr/testify/require"
  9. dbm "github.com/tendermint/tm-db"
  10. "github.com/tendermint/tendermint/internal/eventbus"
  11. "github.com/tendermint/tendermint/internal/evidence"
  12. "github.com/tendermint/tendermint/internal/evidence/mocks"
  13. sm "github.com/tendermint/tendermint/internal/state"
  14. smmocks "github.com/tendermint/tendermint/internal/state/mocks"
  15. sf "github.com/tendermint/tendermint/internal/state/test/factory"
  16. "github.com/tendermint/tendermint/internal/store"
  17. "github.com/tendermint/tendermint/internal/test/factory"
  18. "github.com/tendermint/tendermint/libs/log"
  19. "github.com/tendermint/tendermint/types"
  20. "github.com/tendermint/tendermint/version"
  21. tmpubsub "github.com/tendermint/tendermint/internal/pubsub"
  22. tmquery "github.com/tendermint/tendermint/internal/pubsub/query"
  23. )
  24. const evidenceChainID = "test_chain"
  25. var (
  26. defaultEvidenceTime = time.Date(2019, 1, 1, 0, 0, 0, 0, time.UTC)
  27. defaultEvidenceMaxBytes int64 = 1000
  28. )
  29. func TestEvidencePoolBasic(t *testing.T) {
  30. var (
  31. height = int64(1)
  32. stateStore = &smmocks.Store{}
  33. evidenceDB = dbm.NewMemDB()
  34. blockStore = &mocks.BlockStore{}
  35. )
  36. ctx, cancel := context.WithCancel(context.Background())
  37. defer cancel()
  38. valSet, privVals := factory.ValidatorSet(ctx, t, 1, 10)
  39. blockStore.On("LoadBlockMeta", mock.AnythingOfType("int64")).Return(
  40. &types.BlockMeta{Header: types.Header{Time: defaultEvidenceTime}},
  41. )
  42. stateStore.On("LoadValidators", mock.AnythingOfType("int64")).Return(valSet, nil)
  43. stateStore.On("Load").Return(createState(height+1, valSet), nil)
  44. pool, err := evidence.NewPool(log.TestingLogger(), evidenceDB, stateStore, blockStore, evidence.NopMetrics())
  45. require.NoError(t, err)
  46. require.NoError(t, setupEventBus(ctx, pool))
  47. // evidence not seen yet:
  48. evs, size := pool.PendingEvidence(defaultEvidenceMaxBytes)
  49. require.Equal(t, 0, len(evs))
  50. require.Zero(t, size)
  51. ev, err := types.NewMockDuplicateVoteEvidenceWithValidator(ctx, height, defaultEvidenceTime, privVals[0], evidenceChainID)
  52. require.NoError(t, err)
  53. // good evidence
  54. evAdded := make(chan struct{})
  55. go func() {
  56. <-pool.EvidenceWaitChan()
  57. close(evAdded)
  58. }()
  59. // evidence seen but not yet committed:
  60. err = pool.AddEvidence(ctx, ev)
  61. require.NoError(t, err)
  62. select {
  63. case <-evAdded:
  64. case <-time.After(5 * time.Second):
  65. t.Fatal("evidence was not added to list after 5s")
  66. }
  67. next := pool.EvidenceFront()
  68. require.Equal(t, ev, next.Value.(types.Evidence))
  69. const evidenceBytes int64 = 372
  70. evs, size = pool.PendingEvidence(evidenceBytes)
  71. require.Equal(t, 1, len(evs))
  72. require.Equal(t, evidenceBytes, size) // check that the size of the single evidence in bytes is correct
  73. // shouldn't be able to add evidence twice
  74. err = pool.AddEvidence(ctx, ev)
  75. require.NoError(t, err)
  76. evs, _ = pool.PendingEvidence(defaultEvidenceMaxBytes)
  77. require.Equal(t, 1, len(evs))
  78. }
  79. // Tests inbound evidence for the right time and height
  80. func TestAddExpiredEvidence(t *testing.T) {
  81. ctx, cancel := context.WithCancel(context.Background())
  82. defer cancel()
  83. var (
  84. val = types.NewMockPV()
  85. height = int64(30)
  86. stateStore = initializeValidatorState(ctx, t, val, height)
  87. evidenceDB = dbm.NewMemDB()
  88. blockStore = &mocks.BlockStore{}
  89. expiredEvidenceTime = time.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC)
  90. expiredHeight = int64(2)
  91. )
  92. blockStore.On("LoadBlockMeta", mock.AnythingOfType("int64")).Return(func(h int64) *types.BlockMeta {
  93. if h == height || h == expiredHeight {
  94. return &types.BlockMeta{Header: types.Header{Time: defaultEvidenceTime}}
  95. }
  96. return &types.BlockMeta{Header: types.Header{Time: expiredEvidenceTime}}
  97. })
  98. pool, err := evidence.NewPool(log.TestingLogger(), evidenceDB, stateStore, blockStore, evidence.NopMetrics())
  99. require.NoError(t, err)
  100. require.NoError(t, setupEventBus(ctx, pool))
  101. testCases := []struct {
  102. evHeight int64
  103. evTime time.Time
  104. expErr bool
  105. evDescription string
  106. }{
  107. {height, defaultEvidenceTime, false, "valid evidence"},
  108. {expiredHeight, defaultEvidenceTime, false, "valid evidence (despite old height)"},
  109. {height - 1, expiredEvidenceTime, false, "valid evidence (despite old time)"},
  110. {expiredHeight - 1, expiredEvidenceTime, true,
  111. "evidence from height 1 (created at: 2019-01-01 00:00:00 +0000 UTC) is too old"},
  112. {height, defaultEvidenceTime.Add(1 * time.Minute), true, "evidence time and block time is different"},
  113. }
  114. for _, tc := range testCases {
  115. tc := tc
  116. t.Run(tc.evDescription, func(t *testing.T) {
  117. ctx, cancel := context.WithCancel(context.Background())
  118. defer cancel()
  119. ev, err := types.NewMockDuplicateVoteEvidenceWithValidator(ctx, tc.evHeight, tc.evTime, val, evidenceChainID)
  120. require.NoError(t, err)
  121. err = pool.AddEvidence(ctx, ev)
  122. if tc.expErr {
  123. require.Error(t, err)
  124. } else {
  125. require.NoError(t, err)
  126. }
  127. })
  128. }
  129. }
  130. func TestReportConflictingVotes(t *testing.T) {
  131. var height int64 = 10
  132. ctx, cancel := context.WithCancel(context.Background())
  133. defer cancel()
  134. pool, pv := defaultTestPool(ctx, t, height)
  135. require.NoError(t, setupEventBus(ctx, pool))
  136. val := types.NewValidator(pv.PrivKey.PubKey(), 10)
  137. ev, err := types.NewMockDuplicateVoteEvidenceWithValidator(ctx, height+1, defaultEvidenceTime, pv, evidenceChainID)
  138. require.NoError(t, err)
  139. pool.ReportConflictingVotes(ev.VoteA, ev.VoteB)
  140. // shouldn't be able to submit the same evidence twice
  141. pool.ReportConflictingVotes(ev.VoteA, ev.VoteB)
  142. // evidence from consensus should not be added immediately but reside in the consensus buffer
  143. evList, evSize := pool.PendingEvidence(defaultEvidenceMaxBytes)
  144. require.Empty(t, evList)
  145. require.Zero(t, evSize)
  146. next := pool.EvidenceFront()
  147. require.Nil(t, next)
  148. // move to next height and update state and evidence pool
  149. state := pool.State()
  150. state.LastBlockHeight++
  151. state.LastBlockTime = ev.Time()
  152. state.LastValidators = types.NewValidatorSet([]*types.Validator{val})
  153. pool.Update(ctx, state, []types.Evidence{})
  154. // should be able to retrieve evidence from pool
  155. evList, _ = pool.PendingEvidence(defaultEvidenceMaxBytes)
  156. require.Equal(t, []types.Evidence{ev}, evList)
  157. next = pool.EvidenceFront()
  158. require.NotNil(t, next)
  159. }
  160. func TestEvidencePoolUpdate(t *testing.T) {
  161. height := int64(21)
  162. ctx, cancel := context.WithCancel(context.Background())
  163. defer cancel()
  164. pool, val := defaultTestPool(ctx, t, height)
  165. require.NoError(t, setupEventBus(ctx, pool))
  166. state := pool.State()
  167. // create two lots of old evidence that we expect to be pruned when we update
  168. prunedEv, err := types.NewMockDuplicateVoteEvidenceWithValidator(ctx,
  169. 1,
  170. defaultEvidenceTime.Add(1*time.Minute),
  171. val,
  172. evidenceChainID,
  173. )
  174. require.NoError(t, err)
  175. notPrunedEv, err := types.NewMockDuplicateVoteEvidenceWithValidator(ctx,
  176. 2,
  177. defaultEvidenceTime.Add(2*time.Minute),
  178. val,
  179. evidenceChainID,
  180. )
  181. require.NoError(t, err)
  182. require.NoError(t, pool.AddEvidence(ctx, prunedEv))
  183. require.NoError(t, pool.AddEvidence(ctx, notPrunedEv))
  184. ev, err := types.NewMockDuplicateVoteEvidenceWithValidator(
  185. ctx,
  186. height,
  187. defaultEvidenceTime.Add(21*time.Minute),
  188. val,
  189. evidenceChainID,
  190. )
  191. require.NoError(t, err)
  192. lastCommit := makeCommit(height, val.PrivKey.PubKey().Address())
  193. block := types.MakeBlock(height+1, []types.Tx{}, lastCommit, []types.Evidence{ev})
  194. // update state (partially)
  195. state.LastBlockHeight = height + 1
  196. state.LastBlockTime = defaultEvidenceTime.Add(22 * time.Minute)
  197. evList, _ := pool.PendingEvidence(2 * defaultEvidenceMaxBytes)
  198. require.Equal(t, 2, len(evList))
  199. require.Equal(t, uint32(2), pool.Size())
  200. require.NoError(t, pool.CheckEvidence(ctx, types.EvidenceList{ev}))
  201. evList, _ = pool.PendingEvidence(3 * defaultEvidenceMaxBytes)
  202. require.Equal(t, 3, len(evList))
  203. require.Equal(t, uint32(3), pool.Size())
  204. pool.Update(ctx, state, block.Evidence)
  205. // a) Update marks evidence as committed so pending evidence should be empty
  206. evList, _ = pool.PendingEvidence(defaultEvidenceMaxBytes)
  207. require.Equal(t, []types.Evidence{notPrunedEv}, evList)
  208. // b) If we try to check this evidence again it should fail because it has already been committed
  209. err = pool.CheckEvidence(ctx, types.EvidenceList{ev})
  210. if assert.Error(t, err) {
  211. assert.Equal(t, "evidence was already committed", err.(*types.ErrInvalidEvidence).Reason.Error())
  212. }
  213. }
  214. func TestVerifyPendingEvidencePasses(t *testing.T) {
  215. var height int64 = 1
  216. ctx, cancel := context.WithCancel(context.Background())
  217. defer cancel()
  218. pool, val := defaultTestPool(ctx, t, height)
  219. require.NoError(t, setupEventBus(ctx, pool))
  220. ev, err := types.NewMockDuplicateVoteEvidenceWithValidator(
  221. ctx,
  222. height,
  223. defaultEvidenceTime.Add(1*time.Minute),
  224. val,
  225. evidenceChainID,
  226. )
  227. require.NoError(t, err)
  228. require.NoError(t, pool.AddEvidence(ctx, ev))
  229. require.NoError(t, pool.CheckEvidence(ctx, types.EvidenceList{ev}))
  230. }
  231. func TestVerifyDuplicatedEvidenceFails(t *testing.T) {
  232. var height int64 = 1
  233. ctx, cancel := context.WithCancel(context.Background())
  234. defer cancel()
  235. pool, val := defaultTestPool(ctx, t, height)
  236. require.NoError(t, setupEventBus(ctx, pool))
  237. ev, err := types.NewMockDuplicateVoteEvidenceWithValidator(
  238. ctx,
  239. height,
  240. defaultEvidenceTime.Add(1*time.Minute),
  241. val,
  242. evidenceChainID,
  243. )
  244. require.NoError(t, err)
  245. err = pool.CheckEvidence(ctx, types.EvidenceList{ev, ev})
  246. if assert.Error(t, err) {
  247. assert.Equal(t, "duplicate evidence", err.(*types.ErrInvalidEvidence).Reason.Error())
  248. }
  249. }
  250. // Check that we generate events when evidence is added into the evidence pool
  251. func TestEventOnEvidenceValidated(t *testing.T) {
  252. const height = 1
  253. ctx, cancel := context.WithCancel(context.Background())
  254. defer cancel()
  255. pool, val := defaultTestPool(ctx, t, height)
  256. ev, err := types.NewMockDuplicateVoteEvidenceWithValidator(
  257. ctx,
  258. height,
  259. defaultEvidenceTime.Add(1*time.Minute),
  260. val,
  261. evidenceChainID,
  262. )
  263. require.NoError(t, err)
  264. eventBus := eventbus.NewDefault(log.TestingLogger())
  265. require.NoError(t, eventBus.Start(ctx))
  266. pool.SetEventBus(eventBus)
  267. const query = `tm.event='EvidenceValidated'`
  268. evSub, err := eventBus.SubscribeWithArgs(ctx, tmpubsub.SubscribeArgs{
  269. ClientID: "test",
  270. Query: tmquery.MustCompile(query),
  271. })
  272. require.NoError(t, err)
  273. done := make(chan struct{})
  274. go func() {
  275. defer close(done)
  276. msg, err := evSub.Next(ctx)
  277. assert.NoError(t, err)
  278. edt := msg.Data().(types.EventDataEvidenceValidated)
  279. assert.Equal(t, ev, edt.Evidence)
  280. }()
  281. err = pool.AddEvidence(ctx, ev)
  282. require.NoError(t, err)
  283. select {
  284. case <-done:
  285. case <-time.After(1 * time.Second):
  286. t.Fatal("did not receive a block header after 1 sec.")
  287. }
  288. }
  289. // check that valid light client evidence is correctly validated and stored in
  290. // evidence pool
  291. func TestLightClientAttackEvidenceLifecycle(t *testing.T) {
  292. var (
  293. height int64 = 100
  294. commonHeight int64 = 90
  295. )
  296. ctx, cancel := context.WithCancel(context.Background())
  297. defer cancel()
  298. ev, trusted, common := makeLunaticEvidence(ctx, t, height, commonHeight,
  299. 10, 5, 5, defaultEvidenceTime, defaultEvidenceTime.Add(1*time.Hour))
  300. state := sm.State{
  301. LastBlockTime: defaultEvidenceTime.Add(2 * time.Hour),
  302. LastBlockHeight: 110,
  303. ConsensusParams: *types.DefaultConsensusParams(),
  304. }
  305. stateStore := &smmocks.Store{}
  306. stateStore.On("LoadValidators", height).Return(trusted.ValidatorSet, nil)
  307. stateStore.On("LoadValidators", commonHeight).Return(common.ValidatorSet, nil)
  308. stateStore.On("Load").Return(state, nil)
  309. blockStore := &mocks.BlockStore{}
  310. blockStore.On("LoadBlockMeta", height).Return(&types.BlockMeta{Header: *trusted.Header})
  311. blockStore.On("LoadBlockMeta", commonHeight).Return(&types.BlockMeta{Header: *common.Header})
  312. blockStore.On("LoadBlockCommit", height).Return(trusted.Commit)
  313. blockStore.On("LoadBlockCommit", commonHeight).Return(common.Commit)
  314. pool, err := evidence.NewPool(log.TestingLogger(), dbm.NewMemDB(), stateStore, blockStore, evidence.NopMetrics())
  315. require.NoError(t, err)
  316. require.NoError(t, setupEventBus(ctx, pool))
  317. hash := ev.Hash()
  318. err = pool.AddEvidence(ctx, ev)
  319. require.NoError(t, err)
  320. err = pool.AddEvidence(ctx, ev)
  321. require.NoError(t, err)
  322. pendingEv, _ := pool.PendingEvidence(state.ConsensusParams.Evidence.MaxBytes)
  323. require.Equal(t, 1, len(pendingEv))
  324. require.Equal(t, ev, pendingEv[0])
  325. require.NoError(t, pool.CheckEvidence(ctx, pendingEv))
  326. require.Equal(t, ev, pendingEv[0])
  327. state.LastBlockHeight++
  328. state.LastBlockTime = state.LastBlockTime.Add(1 * time.Minute)
  329. pool.Update(ctx, state, pendingEv)
  330. require.Equal(t, hash, pendingEv[0].Hash())
  331. remaindingEv, _ := pool.PendingEvidence(state.ConsensusParams.Evidence.MaxBytes)
  332. require.Empty(t, remaindingEv)
  333. // evidence is already committed so it shouldn't pass
  334. require.Error(t, pool.CheckEvidence(ctx, types.EvidenceList{ev}))
  335. err = pool.AddEvidence(ctx, ev)
  336. require.NoError(t, err)
  337. remaindingEv, _ = pool.PendingEvidence(state.ConsensusParams.Evidence.MaxBytes)
  338. require.Empty(t, remaindingEv)
  339. }
  340. // Tests that restarting the evidence pool after a potential failure will recover the
  341. // pending evidence and continue to gossip it
  342. func TestRecoverPendingEvidence(t *testing.T) {
  343. ctx, cancel := context.WithCancel(context.Background())
  344. defer cancel()
  345. height := int64(10)
  346. val := types.NewMockPV()
  347. valAddress := val.PrivKey.PubKey().Address()
  348. evidenceDB := dbm.NewMemDB()
  349. stateStore := initializeValidatorState(ctx, t, val, height)
  350. state, err := stateStore.Load()
  351. require.NoError(t, err)
  352. blockStore, err := initializeBlockStore(dbm.NewMemDB(), state, valAddress)
  353. require.NoError(t, err)
  354. // create previous pool and populate it
  355. pool, err := evidence.NewPool(log.TestingLogger(), evidenceDB, stateStore, blockStore, evidence.NopMetrics())
  356. require.NoError(t, err)
  357. require.NoError(t, setupEventBus(ctx, pool))
  358. goodEvidence, err := types.NewMockDuplicateVoteEvidenceWithValidator(
  359. ctx,
  360. height,
  361. defaultEvidenceTime.Add(10*time.Minute),
  362. val,
  363. evidenceChainID,
  364. )
  365. require.NoError(t, err)
  366. expiredEvidence, err := types.NewMockDuplicateVoteEvidenceWithValidator(
  367. ctx,
  368. int64(1),
  369. defaultEvidenceTime.Add(1*time.Minute),
  370. val,
  371. evidenceChainID,
  372. )
  373. require.NoError(t, err)
  374. err = pool.AddEvidence(ctx, goodEvidence)
  375. require.NoError(t, err)
  376. err = pool.AddEvidence(ctx, expiredEvidence)
  377. require.NoError(t, err)
  378. // now recover from the previous pool at a different time
  379. newStateStore := &smmocks.Store{}
  380. newStateStore.On("Load").Return(sm.State{
  381. LastBlockTime: defaultEvidenceTime.Add(25 * time.Minute),
  382. LastBlockHeight: height + 15,
  383. ConsensusParams: types.ConsensusParams{
  384. Block: types.BlockParams{
  385. MaxBytes: 22020096,
  386. MaxGas: -1,
  387. },
  388. Evidence: types.EvidenceParams{
  389. MaxAgeNumBlocks: 20,
  390. MaxAgeDuration: 20 * time.Minute,
  391. MaxBytes: defaultEvidenceMaxBytes,
  392. },
  393. },
  394. }, nil)
  395. newPool, err := evidence.NewPool(log.TestingLogger(), evidenceDB, newStateStore, blockStore, evidence.NopMetrics())
  396. require.NoError(t, err)
  397. evList, _ := newPool.PendingEvidence(defaultEvidenceMaxBytes)
  398. require.Equal(t, 1, len(evList))
  399. next := newPool.EvidenceFront()
  400. require.Equal(t, goodEvidence, next.Value.(types.Evidence))
  401. }
  402. func initializeStateFromValidatorSet(t *testing.T, valSet *types.ValidatorSet, height int64) sm.Store {
  403. stateDB := dbm.NewMemDB()
  404. stateStore := sm.NewStore(stateDB)
  405. state := sm.State{
  406. ChainID: evidenceChainID,
  407. InitialHeight: 1,
  408. LastBlockHeight: height,
  409. LastBlockTime: defaultEvidenceTime,
  410. Validators: valSet,
  411. NextValidators: valSet.CopyIncrementProposerPriority(1),
  412. LastValidators: valSet,
  413. LastHeightValidatorsChanged: 1,
  414. ConsensusParams: types.ConsensusParams{
  415. Block: types.BlockParams{
  416. MaxBytes: 22020096,
  417. MaxGas: -1,
  418. },
  419. Evidence: types.EvidenceParams{
  420. MaxAgeNumBlocks: 20,
  421. MaxAgeDuration: 20 * time.Minute,
  422. MaxBytes: 1000,
  423. },
  424. },
  425. }
  426. // save all states up to height
  427. for i := int64(0); i <= height; i++ {
  428. state.LastBlockHeight = i
  429. require.NoError(t, stateStore.Save(state))
  430. }
  431. return stateStore
  432. }
  433. func initializeValidatorState(ctx context.Context, t *testing.T, privVal types.PrivValidator, height int64) sm.Store {
  434. pubKey, _ := privVal.GetPubKey(ctx)
  435. validator := &types.Validator{Address: pubKey.Address(), VotingPower: 10, PubKey: pubKey}
  436. // create validator set and state
  437. valSet := &types.ValidatorSet{
  438. Validators: []*types.Validator{validator},
  439. Proposer: validator,
  440. }
  441. return initializeStateFromValidatorSet(t, valSet, height)
  442. }
  443. // initializeBlockStore creates a block storage and populates it w/ a dummy
  444. // block at +height+.
  445. func initializeBlockStore(db dbm.DB, state sm.State, valAddr []byte) (*store.BlockStore, error) {
  446. blockStore := store.NewBlockStore(db)
  447. for i := int64(1); i <= state.LastBlockHeight; i++ {
  448. lastCommit := makeCommit(i-1, valAddr)
  449. block, err := sf.MakeBlock(state, i, lastCommit)
  450. if err != nil {
  451. return nil, err
  452. }
  453. block.Header.Time = defaultEvidenceTime.Add(time.Duration(i) * time.Minute)
  454. block.Header.Version = version.Consensus{Block: version.BlockProtocol, App: 1}
  455. const parts = 1
  456. partSet, err := block.MakePartSet(parts)
  457. if err != nil {
  458. return nil, err
  459. }
  460. seenCommit := makeCommit(i, valAddr)
  461. blockStore.SaveBlock(block, partSet, seenCommit)
  462. }
  463. return blockStore, nil
  464. }
  465. func makeCommit(height int64, valAddr []byte) *types.Commit {
  466. commitSigs := []types.CommitSig{{
  467. BlockIDFlag: types.BlockIDFlagCommit,
  468. ValidatorAddress: valAddr,
  469. Timestamp: defaultEvidenceTime,
  470. Signature: []byte("Signature"),
  471. }}
  472. return types.NewCommit(height, 0, types.BlockID{}, commitSigs)
  473. }
  474. func defaultTestPool(ctx context.Context, t *testing.T, height int64) (*evidence.Pool, types.MockPV) {
  475. t.Helper()
  476. val := types.NewMockPV()
  477. valAddress := val.PrivKey.PubKey().Address()
  478. evidenceDB := dbm.NewMemDB()
  479. stateStore := initializeValidatorState(ctx, t, val, height)
  480. state, err := stateStore.Load()
  481. require.NoError(t, err)
  482. blockStore, err := initializeBlockStore(dbm.NewMemDB(), state, valAddress)
  483. require.NoError(t, err)
  484. pool, err := evidence.NewPool(log.TestingLogger(), evidenceDB, stateStore, blockStore, evidence.NopMetrics())
  485. require.NoError(t, err, "test evidence pool could not be created")
  486. return pool, val
  487. }
  488. func createState(height int64, valSet *types.ValidatorSet) sm.State {
  489. return sm.State{
  490. ChainID: evidenceChainID,
  491. LastBlockHeight: height,
  492. LastBlockTime: defaultEvidenceTime,
  493. Validators: valSet,
  494. ConsensusParams: *types.DefaultConsensusParams(),
  495. }
  496. }
  497. func setupEventBus(ctx context.Context, evpool *evidence.Pool) error {
  498. eventBus := eventbus.NewDefault(log.TestingLogger())
  499. if err := eventBus.Start(ctx); err != nil {
  500. return err
  501. }
  502. evpool.SetEventBus(eventBus)
  503. return nil
  504. }