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.

165 lines
4.2 KiB

  1. package light_test
  2. import (
  3. "context"
  4. "os"
  5. "testing"
  6. "time"
  7. "github.com/stretchr/testify/require"
  8. dbm "github.com/tendermint/tm-db"
  9. "github.com/tendermint/tendermint/abci/example/kvstore"
  10. "github.com/tendermint/tendermint/libs/log"
  11. "github.com/tendermint/tendermint/light"
  12. "github.com/tendermint/tendermint/light/provider"
  13. httpp "github.com/tendermint/tendermint/light/provider/http"
  14. dbs "github.com/tendermint/tendermint/light/store/db"
  15. rpctest "github.com/tendermint/tendermint/rpc/test"
  16. "github.com/tendermint/tendermint/types"
  17. )
  18. // NOTE: these are ports of the tests from example_test.go but
  19. // rewritten as more conventional tests.
  20. // Automatically getting new headers and verifying them.
  21. func TestClientIntegration_Update(t *testing.T) {
  22. t.Parallel()
  23. ctx, cancel := context.WithCancel(context.Background())
  24. defer cancel()
  25. conf, err := rpctest.CreateConfig(t.Name())
  26. require.NoError(t, err)
  27. // Start a test application
  28. app := kvstore.NewApplication()
  29. _, closer, err := rpctest.StartTendermint(ctx, conf, app, rpctest.SuppressStdout)
  30. require.NoError(t, err)
  31. defer func() { require.NoError(t, closer(ctx)) }()
  32. // give Tendermint time to generate some blocks
  33. time.Sleep(5 * time.Second)
  34. dbDir, err := os.MkdirTemp("", "light-client-test-update-example")
  35. require.NoError(t, err)
  36. defer os.RemoveAll(dbDir)
  37. chainID := conf.ChainID()
  38. primary, err := httpp.New(chainID, conf.RPC.ListenAddress)
  39. require.NoError(t, err)
  40. // give Tendermint time to generate some blocks
  41. block, err := waitForBlock(ctx, primary, 2)
  42. require.NoError(t, err)
  43. db, err := dbm.NewGoLevelDB("light-client-db", dbDir)
  44. require.NoError(t, err)
  45. c, err := light.NewClient(
  46. ctx,
  47. chainID,
  48. light.TrustOptions{
  49. Period: 504 * time.Hour, // 21 days
  50. Height: 2,
  51. Hash: block.Hash(),
  52. },
  53. primary,
  54. []provider.Provider{primary}, // NOTE: primary should not be used here
  55. dbs.New(db),
  56. light.Logger(log.TestingLogger()),
  57. )
  58. require.NoError(t, err)
  59. defer func() { require.NoError(t, c.Cleanup()) }()
  60. // ensure Tendermint is at height 3 or higher
  61. _, err = waitForBlock(ctx, primary, 3)
  62. require.NoError(t, err)
  63. h, err := c.Update(ctx, time.Now())
  64. require.NoError(t, err)
  65. require.NotNil(t, h)
  66. require.True(t, h.Height > 2)
  67. }
  68. // Manually getting light blocks and verifying them.
  69. func TestClientIntegration_VerifyLightBlockAtHeight(t *testing.T) {
  70. t.Parallel()
  71. ctx, cancel := context.WithCancel(context.Background())
  72. defer cancel()
  73. conf, err := rpctest.CreateConfig(t.Name())
  74. require.NoError(t, err)
  75. // Start a test application
  76. app := kvstore.NewApplication()
  77. _, closer, err := rpctest.StartTendermint(ctx, conf, app, rpctest.SuppressStdout)
  78. require.NoError(t, err)
  79. defer func() { require.NoError(t, closer(ctx)) }()
  80. dbDir, err := os.MkdirTemp("", "light-client-test-verify-example")
  81. require.NoError(t, err)
  82. defer os.RemoveAll(dbDir)
  83. chainID := conf.ChainID()
  84. primary, err := httpp.New(chainID, conf.RPC.ListenAddress)
  85. require.NoError(t, err)
  86. // give Tendermint time to generate some blocks
  87. block, err := waitForBlock(ctx, primary, 2)
  88. require.NoError(t, err)
  89. db, err := dbm.NewGoLevelDB("light-client-db", dbDir)
  90. require.NoError(t, err)
  91. c, err := light.NewClient(ctx,
  92. chainID,
  93. light.TrustOptions{
  94. Period: 504 * time.Hour, // 21 days
  95. Height: 2,
  96. Hash: block.Hash(),
  97. },
  98. primary,
  99. []provider.Provider{primary}, // NOTE: primary should not be used here
  100. dbs.New(db),
  101. light.Logger(log.TestingLogger()),
  102. )
  103. require.NoError(t, err)
  104. defer func() { require.NoError(t, c.Cleanup()) }()
  105. // ensure Tendermint is at height 3 or higher
  106. _, err = waitForBlock(ctx, primary, 3)
  107. require.NoError(t, err)
  108. _, err = c.VerifyLightBlockAtHeight(ctx, 3, time.Now())
  109. require.NoError(t, err)
  110. h, err := c.TrustedLightBlock(3)
  111. require.NoError(t, err)
  112. require.EqualValues(t, 3, h.Height)
  113. }
  114. func waitForBlock(ctx context.Context, p provider.Provider, height int64) (*types.LightBlock, error) {
  115. for {
  116. block, err := p.LightBlock(ctx, height)
  117. switch err {
  118. case nil:
  119. return block, nil
  120. // node isn't running yet, wait 1 second and repeat
  121. case provider.ErrNoResponse, provider.ErrHeightTooHigh:
  122. timer := time.NewTimer(1 * time.Second)
  123. select {
  124. case <-ctx.Done():
  125. return nil, ctx.Err()
  126. case <-timer.C:
  127. }
  128. default:
  129. return nil, err
  130. }
  131. }
  132. }