From edcc837b44a1731c85d91f68b1eee2ce9f77b63c Mon Sep 17 00:00:00 2001 From: Vu Quoc Huy Date: Fri, 27 Oct 2017 23:34:57 +0200 Subject: [PATCH] Rewrite merkletree tests based on work of @ismail from refactor_testing_code branch --- merkletree/merkletree_test.go | 32 ++--- merkletree/pad_test.go | 166 ++++++++++--------------- merkletree/proof_test.go | 225 ++++++++++++++-------------------- merkletree/str_test.go | 16 ++- merkletree/testutil.go | 11 ++ 5 files changed, 186 insertions(+), 264 deletions(-) diff --git a/merkletree/merkletree_test.go b/merkletree/merkletree_test.go index a97e39a..b3b6f28 100644 --- a/merkletree/merkletree_test.go +++ b/merkletree/merkletree_test.go @@ -4,17 +4,12 @@ import ( "bytes" "testing" - "github.com/coniks-sys/coniks-go/crypto/vrf" + "github.com/coniks-sys/coniks-go/crypto" "github.com/coniks-sys/coniks-go/utils" "golang.org/x/crypto/sha3" ) -var vrfPrivKey1, _ = vrf.GenerateKey(bytes.NewReader( - []byte("deterministic tests need 256 bit"))) - -var vrfPrivKey2, _ = vrf.GenerateKey(bytes.NewReader( - []byte("deterministic tests need 32 byte"))) - +// TODO: When #178 is merged, 3 tests below should be removed. func TestOneEntry(t *testing.T) { m, err := NewMerkleTree() if err != nil { @@ -26,7 +21,7 @@ func TestOneEntry(t *testing.T) { key := "key" val := []byte("value") - index := vrfPrivKey1.Compute([]byte(key)) + index := crypto.StaticVRF(t).Compute([]byte(key)) if err := m.Set(index, key, val); err != nil { t.Fatal(err) } @@ -90,10 +85,10 @@ func TestTwoEntries(t *testing.T) { } key1 := "key1" - index1 := vrfPrivKey1.Compute([]byte(key1)) + index1 := crypto.StaticVRF(t).Compute([]byte(key1)) val1 := []byte("value1") key2 := "key2" - index2 := vrfPrivKey1.Compute([]byte(key2)) + index2 := crypto.StaticVRF(t).Compute([]byte(key2)) val2 := []byte("value2") if err := m.Set(index1, key1, val1); err != nil { @@ -130,13 +125,13 @@ func TestThreeEntries(t *testing.T) { } key1 := "key1" - index1 := vrfPrivKey1.Compute([]byte(key1)) + index1 := crypto.StaticVRF(t).Compute([]byte(key1)) val1 := []byte("value1") key2 := "key2" - index2 := vrfPrivKey1.Compute([]byte(key2)) + index2 := crypto.StaticVRF(t).Compute([]byte(key2)) val2 := []byte("value2") key3 := "key3" - index3 := vrfPrivKey1.Compute([]byte(key3)) + index3 := crypto.StaticVRF(t).Compute([]byte(key3)) val3 := []byte("value3") if err := m.Set(index1, key1, val1); err != nil { @@ -191,13 +186,10 @@ func TestThreeEntries(t *testing.T) { } func TestInsertExistedKey(t *testing.T) { - m, err := NewMerkleTree() - if err != nil { - t.Fatal(err) - } + m := newTestTree(t) key1 := "key" - index1 := vrfPrivKey1.Compute([]byte(key1)) + index1 := crypto.StaticVRF(t).Compute([]byte(key1)) val1 := append([]byte(nil), "value"...) if err := m.Set(index1, key1, val1); err != nil { @@ -241,10 +233,10 @@ func TestInsertExistedKey(t *testing.T) { func TestTreeClone(t *testing.T) { key1 := "key1" - index1 := vrfPrivKey1.Compute([]byte(key1)) + index1 := crypto.StaticVRF(t).Compute([]byte(key1)) val1 := []byte("value1") key2 := "key2" - index2 := vrfPrivKey1.Compute([]byte(key2)) + index2 := crypto.StaticVRF(t).Compute([]byte(key2)) val2 := []byte("value2") m1, err := NewMerkleTree() diff --git a/merkletree/pad_test.go b/merkletree/pad_test.go index 18467a2..b563f6a 100644 --- a/merkletree/pad_test.go +++ b/merkletree/pad_test.go @@ -2,6 +2,7 @@ package merkletree import ( "bytes" + "strconv" "testing" "crypto/rand" @@ -10,9 +11,11 @@ import ( "io" "github.com/coniks-sys/coniks-go/crypto/sign" + "github.com/coniks-sys/coniks-go/crypto/vrf" ) var signKey sign.PrivateKey +var vrfKey vrf.PrivateKey func init() { var err error @@ -20,6 +23,10 @@ func init() { if err != nil { panic(err) } + vrfKey, err = vrf.GenerateKey(nil) + if err != nil { + panic(err) + } } type TestAd struct { @@ -35,48 +42,29 @@ func (t TestAd) Serialize() []byte { // 3rd: epoch = 2 (key1, key2) // 4th: epoch = 3 (key1, key2, key3) (latest STR) func TestPADHashChain(t *testing.T) { - key1 := "key" - val1 := []byte("value") - - key2 := "key2" - val2 := []byte("value2") - - key3 := "key3" - val3 := []byte("value3") - + N := uint64(3) treeHashes := make(map[uint64][]byte) - pad, err := NewPAD(TestAd{""}, signKey, vrfPrivKey1, 10) - if err != nil { - t.Fatal(err) + afterCreate := func(pad *PAD) { + treeHashes[0] = append([]byte{}, pad.tree.hash...) } - treeHashes[0] = append([]byte{}, pad.tree.hash...) - - if err := pad.Set(key1, val1); err != nil { - t.Fatal(err) - } - pad.Update(nil) - treeHashes[1] = append([]byte{}, pad.tree.hash...) - - if err := pad.Set(key2, val2); err != nil { - t.Fatal(err) + afterInsert := func(i uint64, pad *PAD) { + pad.Update(nil) + treeHashes[i+1] = append([]byte{}, pad.tree.hash...) } - pad.Update(nil) - treeHashes[2] = append([]byte{}, pad.tree.hash...) - if err := pad.Set(key3, val3); err != nil { + pad, err := createPad(N, keyPrefix, valuePrefix, 10, afterCreate, afterInsert) + if err != nil { t.Fatal(err) } - pad.Update(nil) - treeHashes[3] = append([]byte{}, pad.tree.hash...) - for i := 0; i < 4; i++ { + for i := uint64(0); i < N; i++ { str := pad.GetSTR(uint64(i)) if str == nil { t.Fatal("Cannot get STR #", i) } if !bytes.Equal(str.TreeHash, treeHashes[uint64(i)]) { - t.Fatal("Malformed PAD Update") + t.Fatal("Malformed PAD Update:", i) } if str.Epoch != uint64(i) { @@ -93,66 +81,38 @@ func TestPADHashChain(t *testing.T) { t.Error("Got invalid STR", "want", 3, "got", str.Epoch) } - // lookup - ap, _ := pad.Lookup(key1) - if ap.Leaf.Value == nil { - t.Error("Cannot find key:", key1) - return - } - if !bytes.Equal(ap.Leaf.Value, val1) { - t.Error(key1, "value mismatch") - } - - ap, _ = pad.Lookup(key2) - if ap.Leaf.Value == nil { - t.Error("Cannot find key:", key2) - return - } - if !bytes.Equal(ap.Leaf.Value, val2) { - t.Error(key2, "value mismatch") - } - - ap, _ = pad.Lookup(key3) - if ap.Leaf.Value == nil { - t.Error("Cannot find key:", key3) - return - } - if !bytes.Equal(ap.Leaf.Value, val3) { - t.Error(key3, "value mismatch") - } - - ap, err = pad.LookupInEpoch(key2, 1) - if err != nil { - t.Error(err) - } else if ap.Leaf.Value != nil { - t.Error("Found unexpected key", key2, "in STR #", 1) - } - ap, err = pad.LookupInEpoch(key2, 2) - if err != nil { - t.Error(err) - } else if ap.Leaf.Value == nil { - t.Error("Cannot find key", key2, "in STR #", 2) - } + for i := uint64(0); i < N; i++ { + key := keyPrefix + strconv.FormatUint(i, 10) + val := append(valuePrefix, byte(i)) + ap, _ := pad.Lookup(key) + if ap.Leaf.Value == nil { + t.Fatal("Cannot find key:", key) + } + if !bytes.Equal(ap.Leaf.Value, val) { + t.Error(key, "value mismatch") + } - ap, err = pad.LookupInEpoch(key3, 2) - if err != nil { - t.Error(err) - } else if ap.Leaf.Value != nil { - t.Error("Found unexpected key", key3, "in STR #", 2) } - ap, err = pad.LookupInEpoch(key3, 3) - if err != nil { - t.Error(err) - } else if ap.Leaf.Value == nil { - t.Error("Cannot find key", key3, "in STR #", 3) + for epoch := uint64(0); epoch < N; epoch++ { + for keyNum := uint64(0); keyNum < N; keyNum++ { + key := keyPrefix + strconv.FormatUint(keyNum, 10) + ap, err := pad.LookupInEpoch(key, epoch) + if err != nil { + t.Error(err) + } else if keyNum < epoch && ap.Leaf.Value == nil { + t.Error("Cannot find key", key, "in STR #", epoch) + } else if keyNum >= epoch && ap.Leaf.Value != nil { + t.Error("Found unexpected key", key, "in STR #", epoch) + } + } } } func TestHashChainExceedsMaximumSize(t *testing.T) { var hashChainLimit uint64 = 4 - pad, err := NewPAD(TestAd{""}, signKey, vrfPrivKey2, hashChainLimit) + pad, err := NewPAD(TestAd{""}, signKey, vrfKey, hashChainLimit) if err != nil { t.Fatal(err) } @@ -193,7 +153,7 @@ func TestAssocDataChange(t *testing.T) { key3 := "key3" val3 := []byte("value3") - pad, err := NewPAD(TestAd{""}, signKey, vrfPrivKey1, 10) + pad, err := NewPAD(TestAd{""}, signKey, vrfKey, 10) if err != nil { t.Fatal(err) } @@ -256,16 +216,15 @@ func TestNewPADMissingAssocData(t *testing.T) { t.Fatal("Expected NewPAD to panic if ad are missing.") } }() - if _, err := NewPAD(nil, signKey, vrfPrivKey1, 10); err != nil { + if _, err := NewPAD(nil, signKey, vrfKey, 10); err != nil { t.Fatal("Expected NewPAD to panic but got error.") } } -// TODO move the following to some (internal?) testutils package type testErrorRandReader struct{} func (er testErrorRandReader) Read([]byte) (int, error) { - return 0, errors.New("Not enough entropy!") + return 0, errors.New("not enough entropy") } func mockRandReadWithErroringReader() (orig io.Reader) { @@ -282,7 +241,7 @@ func TestNewPADErrorWhileCreatingTree(t *testing.T) { origRand := mockRandReadWithErroringReader() defer unMockRandReader(origRand) - pad, err := NewPAD(TestAd{""}, signKey, vrfPrivKey1, 3) + pad, err := NewPAD(TestAd{""}, signKey, vrfKey, 3) if err == nil || pad != nil { t.Fatal("NewPad should return an error in case the tree creation failed") } @@ -295,14 +254,11 @@ func BenchmarkCreateLargePAD(b *testing.B) { // total number of entries in tree: NumEntries := uint64(1000000) - // tree.Clone and update STR every: - noUpdate := uint64(NumEntries + 1) b.ResetTimer() // benchmark creating a large tree (don't Update tree) for n := 0; n < b.N; n++ { - _, err := createPad(NumEntries, keyPrefix, valuePrefix, snapLen, - noUpdate) + _, err := createPadSimple(NumEntries, keyPrefix, valuePrefix, snapLen) if err != nil { b.Fatal(err) } @@ -327,9 +283,8 @@ func benchPADUpdate(b *testing.B, entries uint64) { keyPrefix := "key" valuePrefix := []byte("value") snapLen := uint64(10) - noUpdate := uint64(entries + 1) // This takes a lot of time for a large number of entries: - pad, err := createPad(uint64(entries), keyPrefix, valuePrefix, snapLen, noUpdate) + pad, err := createPadSimple(uint64(entries), keyPrefix, valuePrefix, snapLen) if err != nil { b.Fatal(err) } @@ -374,9 +329,13 @@ func benchPADLookup(b *testing.B, entries uint64) { snapLen := uint64(10) keyPrefix := "key" valuePrefix := []byte("value") - updateOnce := uint64(entries - 1) - pad, err := createPad(entries, keyPrefix, valuePrefix, snapLen, - updateOnce) + updateOnce := func(iteration uint64, pad *PAD) { + if iteration == entries-1 { + pad.Update(nil) + } + } + + pad, err := createPad(entries, keyPrefix, valuePrefix, snapLen, nil, updateOnce) if err != nil { b.Fatal(err) } @@ -407,22 +366,31 @@ func benchPADLookup(b *testing.B, entries uint64) { // The STR will get updated every epoch defined by every multiple of // `updateEvery`. If `updateEvery > N` createPAD won't update the STR. func createPad(N uint64, keyPrefix string, valuePrefix []byte, snapLen uint64, - updateEvery uint64) (*PAD, error) { - pad, err := NewPAD(TestAd{""}, signKey, vrfPrivKey1, snapLen) + afterCreateCB func(pad *PAD), + afterInsertCB func(iteration uint64, pad *PAD)) (*PAD, error) { + pad, err := NewPAD(TestAd{""}, signKey, vrfKey, snapLen) if err != nil { return nil, err } + if afterCreateCB != nil { + afterCreateCB(pad) + } for i := uint64(0); i < N; i++ { - key := keyPrefix + string(i) + key := keyPrefix + strconv.FormatUint(i, 10) value := append(valuePrefix, byte(i)) if err := pad.Set(key, value); err != nil { return nil, fmt.Errorf("Couldn't set key=%s and value=%s. Error: %v", key, value, err) } - if i != 0 && (i%updateEvery == 0) { - pad.Update(nil) + if afterInsertCB != nil { + afterInsertCB(i, pad) } } return pad, nil } + +func createPadSimple(N uint64, keyPrefix string, valuePrefix []byte, + snapLen uint64) (*PAD, error) { + return createPad(N, keyPrefix, valuePrefix, snapLen, nil, nil) +} diff --git a/merkletree/proof_test.go b/merkletree/proof_test.go index e8ab46f..26ebe88 100644 --- a/merkletree/proof_test.go +++ b/merkletree/proof_test.go @@ -2,192 +2,145 @@ package merkletree import ( "bytes" + "math/rand" + "strconv" "testing" + "time" + "github.com/coniks-sys/coniks-go/crypto" "github.com/coniks-sys/coniks-go/utils" ) -func TestVerifyProof(t *testing.T) { - m, err := NewMerkleTree() - if err != nil { - t.Fatal(err) - } - - key1 := "key1" - index1 := vrfPrivKey1.Compute([]byte(key1)) - val1 := []byte("value1") - key2 := "key2" - index2 := vrfPrivKey1.Compute([]byte(key2)) - val2 := []byte("value2") - key3 := "key3" - index3 := vrfPrivKey1.Compute([]byte(key3)) - val3 := []byte("value3") - - if err := m.Set(index1, key1, val1); err != nil { - t.Fatal(err) - } - if err := m.Set(index2, key2, val2); err != nil { - t.Fatal(err) - } - if err := m.Set(index3, key3, val3); err != nil { - t.Fatal(err) - } - - m.recomputeHash() - - ap1 := m.Get(index1) - if ap1.Leaf.Value == nil { - t.Error("Cannot find key:", key1) - return - } - ap2 := m.Get(index2) - if ap2.Leaf.Value == nil { - t.Error("Cannot find key:", key2) - return - } - ap3 := m.Get(index3) - if ap3.Leaf.Value == nil { - t.Error("Cannot find key:", key3) - return - } +type mockTest struct { + key string + value []byte + index []byte + want ProofType +} - // proof of inclusion - proof := m.Get(index3) - if proof.Leaf.Value == nil { - t.Fatal("Expect returned leaf's value is not nil") - } - // ensure this is a proof of inclusion by comparing the returned indices - // and verifying the VRF index as well. - if !bytes.Equal(proof.LookupIndex, proof.Leaf.Index) || - !bytes.Equal(vrfPrivKey1.Compute([]byte(key3)), proof.LookupIndex) { - t.Fatal("Expect a proof of inclusion") - } - // verify auth path - if proof.Verify([]byte(key3), val3, m.hash) != nil { - t.Error("Proof of inclusion verification failed.") - } +const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" +const ( + letterIdxBits = 6 // 6 bits to represent a letter index + letterIdxMask = 1<= 0; { + if remain == 0 { + cache, remain = src.Int63(), letterIdxMax + } + if idx := int(cache & letterIdxMask); idx < len(letterBytes) { + b[i] = letterBytes[idx] + i-- + } + cache >>= letterIdxBits + remain-- + } + + return string(b) } -func TestVerifyProofSamePrefix(t *testing.T) { - m, err := NewMerkleTree() - if err != nil { - t.Fatal(err) - } - - key1 := "key1" - index1 := vrfPrivKey1.Compute([]byte(key1)) - val1 := []byte("value1") - if err := m.Set(index1, key1, val1); err != nil { - t.Fatal(err) - } +var N uint64 = 3 // number of inclusions. + +func setup(t *testing.T) (*MerkleTree, []*mockTest) { + m := newTestTree(t) + + tuple := []*mockTest{} + for i := uint64(0); i < uint64(N); i++ { + key := keyPrefix + strconv.FormatUint(i, 10) + val := append(valuePrefix, byte(i)) + index := crypto.StaticVRF(t).Compute([]byte(key)) + if err := m.Set(index, key, val); err != nil { + t.Fatal(err) + } + tuple = append(tuple, &mockTest{key, val, index, ProofOfInclusion}) + } + + sharedPrefix := tuple[0].index + var absentKey string + var absentIndex []byte + for { + absentKey = RandStringBytesMaskImprSrc(3) + absentIndex = crypto.StaticVRF(t).Compute([]byte(absentKey)) + proof := m.Get(absentIndex) + // assert these indices share the same prefix in the first bit + if bytes.Equal(utils.ToBytes(utils.ToBits(sharedPrefix)[:proof.Leaf.Level]), + utils.ToBytes(utils.ToBits(absentIndex)[:proof.Leaf.Level])) { + break + } + } + + tuple = append(tuple, &mockTest{absentKey, nil, absentIndex, ProofOfAbsence}) m.recomputeHash() - absentIndex := vrfPrivKey1.Compute([]byte("a")) - proof := m.Get(absentIndex) // shares the same prefix with leaf node key1 - if proof.Leaf.Value != nil { - t.Fatal("Expect returned leaf's value is nil") - } - // ensure this is a proof of absence - if bytes.Equal(proof.LookupIndex, proof.Leaf.Index) || - !bytes.Equal(vrfPrivKey1.Compute([]byte("a")), proof.LookupIndex) { - t.Fatal("Expect a proof of absence") - } - // assert these indices share the same prefix in the first bit - if !bytes.Equal(utils.ToBytes(utils.ToBits(index1)[:proof.Leaf.Level]), - utils.ToBytes(utils.ToBits(absentIndex)[:proof.Leaf.Level])) { - t.Fatal("Expect these indices share the same prefix in the first bit") - } - if proof.Verify([]byte("a"), nil, m.hash) != nil { - t.Error("Proof of absence verification failed.") - } + return m, tuple +} - // re-get proof of inclusion - // for testing the commitment assignment - proof = m.Get(index1) - if proof.Leaf.Value == nil { - t.Fatal("Expect returned leaf's value is not nil") - } - // ensure this is a proof of inclusion by comparing the returned indices - // and verifying the VRF index as well. - if !bytes.Equal(proof.LookupIndex, proof.Leaf.Index) || - !bytes.Equal(vrfPrivKey1.Compute([]byte(key1)), proof.LookupIndex) { - t.Fatal("Expect a proof of inclusion") - } - // step 2. verify auth path - if proof.Verify([]byte(key1), val1, m.hash) != nil { - t.Error("Proof of inclusion verification failed.") +func TestVerifyProof(t *testing.T) { + m, tests := setup(t) + + for _, tt := range tests { + proof := m.Get(tt.index) + if got, want := proof.ProofType(), tt.want; got != want { + t.Error("TestVerifyProof() failed with tuple(", tt.key, tt.value, ")") + } + if proof.Verify([]byte(tt.key), tt.value, m.hash) != nil { + t.Error("TestVerifyProof() failed with tuple(", tt.key, tt.value, ")") + } } } func TestProofVerificationErrors(t *testing.T) { - m, err := NewMerkleTree() - if err != nil { - t.Fatal(err) - } + m, tuple := setup(t) - key1 := "key1" - index1 := vrfPrivKey1.Compute([]byte(key1)) - val1 := []byte("value1") - if err := m.Set(index1, key1, val1); err != nil { - t.Fatal(err) - } - m.recomputeHash() - absentIndex := vrfPrivKey1.Compute([]byte("a")) + index, key, value := tuple[0].index, tuple[0].key, tuple[0].value // ProofOfInclusion // assert proof of inclusion - proof1 := m.Get(index1) + proof1 := m.Get(index) if proof1.ProofType() != ProofOfInclusion { t.Fatal("Expect a proof of inclusion") } // - ErrBindingsDiffer proof1.Leaf.Value[0] += 1 - if err := proof1.Verify([]byte(key1), val1, m.hash); err != ErrBindingsDiffer { + if err := proof1.Verify([]byte(key), value, m.hash); err != ErrBindingsDiffer { t.Error("Expect", ErrBindingsDiffer, "got", err) } // - ErrUnverifiableCommitment proof1.Leaf.Value[0] -= 1 proof1.Leaf.Commitment.Salt[0] += 1 - if err := proof1.Verify([]byte(key1), val1, m.hash); err != ErrUnverifiableCommitment { + if err := proof1.Verify([]byte(key), value, m.hash); err != ErrUnverifiableCommitment { t.Error("Expect", ErrUnverifiableCommitment, "got", err) } // ErrUnequalTreeHashes hash := append([]byte{}, m.hash...) hash[0] += 1 proof1.Leaf.Commitment.Salt[0] -= 1 - if err := proof1.Verify([]byte(key1), val1, hash); err != ErrUnequalTreeHashes { + if err := proof1.Verify([]byte(key), value, hash); err != ErrUnequalTreeHashes { t.Error("Expect", ErrUnequalTreeHashes, "got", err) } // ProofOfAbsence - proof2 := m.Get(absentIndex) // shares the same prefix with leaf node key1 + index, key, value = tuple[N].index, tuple[N].key, tuple[N].value + proof2 := m.Get(index) // shares the same prefix with leaf node key1 // assert proof of absence if proof2.ProofType() != ProofOfAbsence { t.Fatal("Expect a proof of absence") } // - ErrBindingsDiffer proof2.Leaf.Value = make([]byte, 1) - if err := proof2.Verify([]byte("a"), nil, m.hash); err != ErrBindingsDiffer { + if err := proof2.Verify([]byte(key), value, m.hash); err != ErrBindingsDiffer { t.Error("Expect", ErrBindingsDiffer, "got", err) } // - ErrIndicesMismatch proof2.Leaf.Value = nil proof2.Leaf.Index[0] &= 0x01 - if err := proof2.Verify([]byte("a"), nil, m.hash); err != ErrIndicesMismatch { + if err := proof2.Verify([]byte(key), value, m.hash); err != ErrIndicesMismatch { t.Error("Expect", ErrIndicesMismatch, "got", err) } } diff --git a/merkletree/str_test.go b/merkletree/str_test.go index 82fb88d..0382bde 100644 --- a/merkletree/str_test.go +++ b/merkletree/str_test.go @@ -1,23 +1,21 @@ package merkletree -import "testing" +import ( + "testing" + + "github.com/coniks-sys/coniks-go/crypto" +) func TestVerifyHashChain(t *testing.T) { var N uint64 = 100 - keyPrefix := "key" - valuePrefix := []byte("value") - pad, err := NewPAD(TestAd{"abc"}, signKey, vrfPrivKey1, 10) + pad, err := NewPAD(TestAd{"abc"}, crypto.StaticSigning(t), crypto.StaticVRF(t), N) if err != nil { t.Fatal(err) } savedSTR := pad.LatestSTR() - - pk, ok := pad.signKey.Public() - if !ok { - t.Fatal("Couldn't retrieve public-key.") - } + pk, _ := pad.signKey.Public() for i := uint64(1); i < N; i++ { key := keyPrefix + string(i) diff --git a/merkletree/testutil.go b/merkletree/testutil.go index 74b1f5e..eeef7d8 100644 --- a/merkletree/testutil.go +++ b/merkletree/testutil.go @@ -6,6 +6,9 @@ import ( "github.com/coniks-sys/coniks-go/crypto" ) +var keyPrefix = "key" +var valuePrefix = []byte("value") + // StaticPAD returns a pad with a static initial STR for _tests_. func StaticPAD(t *testing.T, ad AssocData) *PAD { pad, err := NewPAD(ad, crypto.StaticSigning(t), crypto.StaticVRF(t), 10) @@ -26,3 +29,11 @@ func staticTree(t *testing.T) *MerkleTree { m.nonce = []byte{} return m } + +func newTestTree(t *testing.T) *MerkleTree { + m, err := NewMerkleTree() + if err != nil { + t.Fatal(err) + } + return m +}