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.

166 lines
4.3 KiB

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