Support non-existence proof
This commit is contained in:
parent
538824d736
commit
2b735d8968
|
@ -55,62 +55,81 @@ func Get(key []byte, prove bool) (data.Bytes, uint64, error) {
|
|||
resp, err := node.ABCIQuery("/key", key, false)
|
||||
return data.Bytes(resp.Value), resp.Height, err
|
||||
}
|
||||
val, h, _, err := GetWithProof(key)
|
||||
val, h, _, _, err := GetWithProof(key)
|
||||
return val, h, err
|
||||
}
|
||||
|
||||
// GetWithProof returns the values stored under a given key at the named
|
||||
// height as in Get. Additionally, it will return a validated merkle
|
||||
// proof for the key-value pair if it exists, and all checks pass.
|
||||
func GetWithProof(key []byte) (data.Bytes, uint64, *iavl.KeyExistsProof, error) {
|
||||
func GetWithProof(key []byte) (data.Bytes, uint64,
|
||||
*iavl.KeyExistsProof, *iavl.KeyNotExistsProof, error) {
|
||||
|
||||
node := commands.GetNode()
|
||||
cert, err := commands.GetCertifier()
|
||||
if err != nil {
|
||||
return nil, 0, nil, err
|
||||
return nil, 0, nil, nil, err
|
||||
}
|
||||
return CustomGetWithProof(key, node, cert)
|
||||
}
|
||||
|
||||
// TODO: fix this up alexis
|
||||
func CustomGetWithProof(key []byte, node client.Client,
|
||||
cert Certifier) (data.Bytes, uint64, *iavl.KeyExistsProof, error) {
|
||||
func CustomGetWithProof(key []byte, node client.Client, cert Certifier) (data.Bytes, uint64,
|
||||
*iavl.KeyExistsProof, *iavl.KeyNotExistsProof, error) {
|
||||
|
||||
resp, err := node.ABCIQuery("/key", key, true)
|
||||
if err != nil {
|
||||
return nil, 0, nil, err
|
||||
return nil, 0, nil, nil, err
|
||||
}
|
||||
ph := int(resp.Height)
|
||||
|
||||
// make sure the proof is the proper height
|
||||
if !resp.Code.IsOK() {
|
||||
return nil, 0, nil, errors.Errorf("Query error %d: %s", resp.Code, resp.Code.String())
|
||||
return nil, 0, nil, nil, errors.Errorf("Query error %d: %s", resp.Code, resp.Code.String())
|
||||
}
|
||||
// TODO: Handle null proofs
|
||||
if len(resp.Key) == 0 || len(resp.Value) == 0 || len(resp.Proof) == 0 {
|
||||
return nil, 0, nil, lc.ErrNoData()
|
||||
if len(resp.Key) == 0 || len(resp.Proof) == 0 {
|
||||
return nil, 0, nil, nil, lc.ErrNoData()
|
||||
}
|
||||
if ph != 0 && ph != int(resp.Height) {
|
||||
return nil, 0, nil, lc.ErrHeightMismatch(ph, int(resp.Height))
|
||||
return nil, 0, nil, nil, lc.ErrHeightMismatch(ph, int(resp.Height))
|
||||
}
|
||||
|
||||
check, err := GetCertifiedCheckpoint(ph, node, cert)
|
||||
if err != nil {
|
||||
return nil, 0, nil, err
|
||||
return nil, 0, nil, nil, err
|
||||
}
|
||||
|
||||
proof := new(iavl.KeyExistsProof)
|
||||
if len(resp.Value) > 0 {
|
||||
// The key was found, construct a proof of existence.
|
||||
proof := new(iavl.KeyExistsProof)
|
||||
err = wire.ReadBinaryBytes(resp.Proof, &proof)
|
||||
if err != nil {
|
||||
return nil, 0, nil, nil, err
|
||||
}
|
||||
|
||||
// validate the proof against the certified header to ensure data integrity
|
||||
err = proof.Verify(resp.Key, resp.Value, check.Header.AppHash)
|
||||
if err != nil {
|
||||
return nil, 0, nil, nil, err
|
||||
}
|
||||
|
||||
return data.Bytes(resp.Value), resp.Height, proof, nil, nil
|
||||
}
|
||||
|
||||
// The key wasn't found, construct a proof of non-existence.
|
||||
proof := new(iavl.KeyNotExistsProof)
|
||||
err = wire.ReadBinaryBytes(resp.Proof, &proof)
|
||||
if err != nil {
|
||||
return nil, 0, nil, err
|
||||
return nil, 0, nil, nil, err
|
||||
}
|
||||
|
||||
// validate the proof against the certified header to ensure data integrity
|
||||
err = proof.Verify(resp.Key, resp.Value, check.Header.AppHash)
|
||||
err = proof.Verify(resp.Key, check.Header.AppHash)
|
||||
if err != nil {
|
||||
return nil, 0, nil, err
|
||||
return nil, 0, nil, nil, err
|
||||
}
|
||||
|
||||
return data.Bytes(resp.Value), resp.Height, proof, nil
|
||||
return data.Bytes(resp.Value), resp.Height, nil, proof, nil
|
||||
}
|
||||
|
||||
// GetCertifiedCheckpoint gets the signed header for a given height
|
||||
|
|
|
@ -65,9 +65,9 @@ func TestAppProofs(t *testing.T) {
|
|||
|
||||
// Test existing key.
|
||||
|
||||
bs, _, proof, err := CustomGetWithProof(k, cl, cert)
|
||||
bs, _, proofExists, _, err := CustomGetWithProof(k, cl, cert)
|
||||
require.Nil(err, "%+v", err)
|
||||
require.NotNil(proof)
|
||||
require.NotNil(proofExists)
|
||||
|
||||
var data eyes.Data
|
||||
err = wire.ReadBinaryBytes(bs, &data)
|
||||
|
@ -76,10 +76,10 @@ func TestAppProofs(t *testing.T) {
|
|||
|
||||
// Test non-existing key.
|
||||
|
||||
// TODO: This currently fails.
|
||||
missing := []byte("my-missing-key")
|
||||
bs, _, proof, err = CustomGetWithProof(missing, cl, cert)
|
||||
bs, _, proofExists, proofNotExists, err := CustomGetWithProof(missing, cl, cert)
|
||||
require.Nil(err, "%+v", err)
|
||||
require.Nil(bs)
|
||||
require.NotNil(proof)
|
||||
require.Nil(proofExists)
|
||||
require.NotNil(proofNotExists)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue