2021-12-04 16:42:11 +00:00

210 lines
4.8 KiB
Go

package graviton
import (
"math/rand"
"testing"
"time"
"github.com/stretchr/testify/require"
)
func TestTreeProve(t *testing.T) {
rand.Seed(100)
_, tree := setupDeterministicTree(t, 10)
key := make([]byte, 20)
value := make([]byte, 10)
rand.Read(key)
rand.Read(value)
require.NoError(t, tree.Put(key, value))
proof, err := tree.GenerateProof(key)
require.NoError(t, err)
require.True(t, proof.VerifyMembership(tree.hashSkipError(), key))
mproof := proof.Marshal()
var decoded Proof
decoded.Unmarshal(mproof)
require.True(t, decoded.VerifyMembership(tree.hashSkipError(), key))
require.False(t, decoded.VerifyNonMembership(tree.hashSkipError(), key))
// value is last 11 bytes
copy(mproof[len(mproof)-11:], []byte{0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88})
require.Error(t, decoded.Unmarshal(mproof))
// test malformed proofs, small buffer give array indexing array
wrong_proof := []byte{1, collision, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88}
require.Error(t, decoded.Unmarshal(wrong_proof))
}
func TestTreeProvePersistent(t *testing.T) {
_, tree := setupDeterministicTree(t, 4)
var key = make([]byte, 10)
rand.Read(key)
require.NoError(t, tree.Put(key, key))
root := tree.hashSkipError()
require.NoError(t, tree.Commit())
proof, err := tree.GenerateProof(key)
require.NoError(t, err)
require.True(t, proof.VerifyMembership(tree.hashSkipError(), key))
require.Equal(t, key, proof.Value())
require.True(t, proof.VerifyMembership(root, key))
proof.Reset()
if len(proof.Value()) != 0 {
t.Fatalf("Proof not successfully reset.")
}
}
// these cannot be generated using exported api
func TestProveCollision(t *testing.T) {
_, tree := setupDeterministicTree(t, 0)
value := []byte("testcollision")
for i := 0; i < 8; i++ {
key := [HASHSIZE]byte{}
key[0] = 1 << uint(i)
require.NoError(t, tree.putRaw(key, nil, value))
}
key := [HASHSIZE]byte{}
key[0] = 0xf0 // this needs to be flipped if if bit prrocessing is switched
require.NoError(t, tree.putRaw(key, nil, value))
root := tree.hashSkipError()
//require.NoError(t, tree.Commit())
ckey := [HASHSIZE]byte{}
ckey[0] = 0xf8 // this needs to be flipped if if bit prrocessing is switched
proof := NewProof()
require.NoError(t, tree.generateProofRaw(ckey, proof))
require.False(t, proof.verifyMembershipRaw(root, key))
require.True(t, proof.verifyNonMembershipRaw(root, key))
}
func TestProveDeadend(t *testing.T) {
_, tree := setupDeterministicTree(t, 0)
value := []byte("testdeadend")
gET_CHECKED = false // disable error checking of values
defer func() {
gET_CHECKED = true
}()
order := []byte{
0x0, //00000000,
0xc0, //11000000,
0xd0, //11010000,
0x8, //10000000,
}
for i := range order {
key := [HASHSIZE]byte{}
key[0] = order[i]
require.NoError(t, tree.putRaw(key, nil, value))
}
key := [HASHSIZE]byte{}
key[0] = 0xE0 //11100000
root := tree.hashSkipError()
require.NoError(t, tree.Commit())
proof := NewProof()
require.NoError(t, tree.generateProofRaw(key, proof))
require.False(t, proof.verifyMembershipRaw(root, key))
require.True(t, proof.verifyNonMembershipRaw(root, key))
{
order := []byte{
0x0, //00000000,
0x20, //11000000,
0xd0, //11010000,
0x8, //10000000,
}
for i := range order {
key := [HASHSIZE]byte{}
key[0] = order[i]
require.NoError(t, tree.putRaw(key, nil, value))
}
key := [HASHSIZE]byte{}
key[0] = 0xE0 //11100000
//root := tree.Hash()
require.NoError(t, tree.Commit())
}
}
func TestProofMarshal(t *testing.T) {
_, tree := setupDeterministicTree(t, 1000)
root := tree.hashSkipError()
key := make([]byte, 20)
for i := 0; i < 10; i++ {
rand.Read(key)
proof, err := tree.GenerateProof(key[:])
require.NoError(t, err)
member := proof.VerifyMembership(root, key)
non := proof.VerifyNonMembership(root, key)
buf := proof.Marshal()
marshalled := NewProof()
marshalled.Unmarshal(buf)
require.Equal(t, proof, marshalled)
require.Equal(t, member, marshalled.VerifyMembership(root, key))
require.Equal(t, non, marshalled.VerifyNonMembership(root, key))
proof.Reset()
}
}
func TestProveAfterDelete(t *testing.T) {
rand.Seed(time.Now().UnixNano())
_, tree := setupDeterministicTree(t, 0)
proof := NewProof()
key1 := make([]byte, 20)
rand.Read(key1)
require.NoError(t, tree.Put(key1, key1))
keys := [][]byte{}
for i := 0; i < 7; i++ {
key2 := make([]byte, 20)
rand.Read(key2)
require.NoError(t, tree.Put(key2, key2))
keys = append(keys, key2)
}
proof, err := tree.GenerateProof(key1[:])
require.NoError(t, err)
require.True(t, proof.VerifyMembership(tree.hashSkipError(), key1))
for _, key := range keys {
require.NoError(t, tree.Delete(key))
}
proof.Reset()
proof, err = tree.GenerateProof(key1[:])
require.NoError(t, err)
require.True(t, proof.VerifyMembership(tree.hashSkipError(), key1))
}