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