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.

159 lines
4.8 KiB

  1. package proxy
  2. import (
  3. "fmt"
  4. "os"
  5. "testing"
  6. "time"
  7. "github.com/stretchr/testify/assert"
  8. "github.com/stretchr/testify/require"
  9. "github.com/tendermint/tendermint/abci/example/kvstore"
  10. "github.com/tendermint/tendermint/crypto/merkle"
  11. "github.com/tendermint/tendermint/lite"
  12. certclient "github.com/tendermint/tendermint/lite/client"
  13. nm "github.com/tendermint/tendermint/node"
  14. "github.com/tendermint/tendermint/rpc/client"
  15. rpctest "github.com/tendermint/tendermint/rpc/test"
  16. "github.com/tendermint/tendermint/types"
  17. )
  18. var node *nm.Node
  19. var chainID = "tendermint_test" // TODO use from config.
  20. var waitForEventTimeout = 5 * time.Second
  21. // TODO fix tests!!
  22. func TestMain(m *testing.M) {
  23. app := kvstore.NewKVStoreApplication()
  24. node = rpctest.StartTendermint(app)
  25. code := m.Run()
  26. node.Stop()
  27. node.Wait()
  28. os.Exit(code)
  29. }
  30. func kvstoreTx(k, v []byte) []byte {
  31. return []byte(fmt.Sprintf("%s=%s", k, v))
  32. }
  33. // TODO: enable it after general proof format has been adapted
  34. // in abci/examples/kvstore.go
  35. func _TestAppProofs(t *testing.T) {
  36. assert, require := assert.New(t), require.New(t)
  37. prt := defaultProofRuntime()
  38. cl := client.NewLocal(node)
  39. client.WaitForHeight(cl, 1, nil)
  40. // This sets up our trust on the node based on some past point.
  41. source := certclient.NewProvider(chainID, cl)
  42. seed, err := source.LatestFullCommit(chainID, 1, 1)
  43. require.NoError(err, "%#v", err)
  44. cert := lite.NewBaseVerifier(chainID, seed.Height(), seed.Validators)
  45. // Wait for tx confirmation.
  46. done := make(chan int64)
  47. go func() {
  48. evtTyp := types.EventTx
  49. _, err = client.WaitForOneEvent(cl, evtTyp, waitForEventTimeout)
  50. require.Nil(err, "%#v", err)
  51. close(done)
  52. }()
  53. // Submit a transaction.
  54. k := []byte("my-key")
  55. v := []byte("my-value")
  56. tx := kvstoreTx(k, v)
  57. br, err := cl.BroadcastTxCommit(tx)
  58. require.NoError(err, "%#v", err)
  59. require.EqualValues(0, br.CheckTx.Code, "%#v", br.CheckTx)
  60. require.EqualValues(0, br.DeliverTx.Code)
  61. brh := br.Height
  62. // Fetch latest after tx commit.
  63. <-done
  64. latest, err := source.LatestFullCommit(chainID, 1, 1<<63-1)
  65. require.NoError(err, "%#v", err)
  66. rootHash := latest.SignedHeader.AppHash
  67. if rootHash == nil {
  68. // Fetch one block later, AppHash hasn't been committed yet.
  69. // TODO find a way to avoid doing this.
  70. client.WaitForHeight(cl, latest.SignedHeader.Height+1, nil)
  71. latest, err = source.LatestFullCommit(chainID, latest.SignedHeader.Height+1, 1<<63-1)
  72. require.NoError(err, "%#v", err)
  73. rootHash = latest.SignedHeader.AppHash
  74. }
  75. require.NotNil(rootHash)
  76. // verify a query before the tx block has no data (and valid non-exist proof)
  77. bs, height, proof, err := GetWithProof(prt, k, brh-1, cl, cert)
  78. require.NoError(err, "%#v", err)
  79. // require.NotNil(proof)
  80. // TODO: Ensure that *some* keys will be there, ensuring that proof is nil,
  81. // (currently there's a race condition)
  82. // and ensure that proof proves absence of k.
  83. require.Nil(bs)
  84. // but given that block it is good
  85. bs, height, proof, err = GetWithProof(prt, k, brh, cl, cert)
  86. require.NoError(err, "%#v", err)
  87. require.NotNil(proof)
  88. require.Equal(height, brh)
  89. assert.EqualValues(v, bs)
  90. err = prt.VerifyValue(proof, rootHash, string(k), bs) // XXX key encoding
  91. assert.NoError(err, "%#v", err)
  92. // Test non-existing key.
  93. missing := []byte("my-missing-key")
  94. bs, _, proof, err = GetWithProof(prt, missing, 0, cl, cert)
  95. require.NoError(err)
  96. require.Nil(bs)
  97. require.NotNil(proof)
  98. err = prt.VerifyAbsence(proof, rootHash, string(missing)) // XXX VerifyAbsence(), keyencoding
  99. assert.NoError(err, "%#v", err)
  100. err = prt.VerifyAbsence(proof, rootHash, string(k)) // XXX VerifyAbsence(), keyencoding
  101. assert.Error(err, "%#v", err)
  102. }
  103. func TestTxProofs(t *testing.T) {
  104. assert, require := assert.New(t), require.New(t)
  105. cl := client.NewLocal(node)
  106. client.WaitForHeight(cl, 1, nil)
  107. tx := kvstoreTx([]byte("key-a"), []byte("value-a"))
  108. br, err := cl.BroadcastTxCommit(tx)
  109. require.NoError(err, "%#v", err)
  110. require.EqualValues(0, br.CheckTx.Code, "%#v", br.CheckTx)
  111. require.EqualValues(0, br.DeliverTx.Code)
  112. brh := br.Height
  113. source := certclient.NewProvider(chainID, cl)
  114. seed, err := source.LatestFullCommit(chainID, brh-2, brh-2)
  115. require.NoError(err, "%#v", err)
  116. cert := lite.NewBaseVerifier(chainID, seed.Height(), seed.Validators)
  117. // First let's make sure a bogus transaction hash returns a valid non-existence proof.
  118. key := types.Tx([]byte("bogus")).Hash()
  119. res, err := cl.Tx(key, true)
  120. require.NotNil(err)
  121. require.Contains(err.Error(), "not found")
  122. // Now let's check with the real tx root hash.
  123. key = types.Tx(tx).Hash()
  124. res, err = cl.Tx(key, true)
  125. require.NoError(err, "%#v", err)
  126. require.NotNil(res)
  127. keyHash := merkle.SimpleHashFromByteSlices([][]byte{key})
  128. err = res.Proof.Validate(keyHash)
  129. assert.NoError(err, "%#v", err)
  130. commit, err := GetCertifiedCommit(br.Height, cl, cert)
  131. require.Nil(err, "%#v", err)
  132. require.Equal(res.Proof.RootHash, commit.Header.DataHash)
  133. }