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