aboutsummaryrefslogtreecommitdiff
path: root/trillian_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'trillian_test.go')
-rw-r--r--trillian_test.go302
1 files changed, 94 insertions, 208 deletions
diff --git a/trillian_test.go b/trillian_test.go
index b3c1653..1b0c923 100644
--- a/trillian_test.go
+++ b/trillian_test.go
@@ -5,11 +5,9 @@ import (
"testing"
"github.com/google/trillian"
- "github.com/google/trillian/types"
- "google.golang.org/grpc/codes"
- "google.golang.org/grpc/status"
-
- "github.com/system-transparency/stfe/namespace/testdata"
+ ttypes "github.com/google/trillian/types"
+ "github.com/system-transparency/stfe/testdata"
+ "github.com/system-transparency/stfe/types"
)
func TestCheckQueueLeaf(t *testing.T) {
@@ -20,30 +18,31 @@ func TestCheckQueueLeaf(t *testing.T) {
wantErr bool
}{
{
- description: "bad response: trillian error",
+ description: "invalid: no Trillian response: error",
err: fmt.Errorf("backend error"),
wantErr: true,
},
{
- description: "bad response: empty",
+ description: "invalid: no Trillian response: nil",
wantErr: true,
},
{
- description: "bad response: no queued leaf",
+ description: "invalid: no Trillian response: empty",
rsp: &trillian.QueueLeafResponse{},
wantErr: true,
},
{
- description: "ok response: duplicate leaf",
- rsp: makeTrillianQueueLeafResponse(t, testPackage, testdata.Ed25519Vk, testdata.Ed25519Sk, true),
+ description: "valid: gRPC status: duplicate",
+ rsp: testdata.DefaultTQlr(t, true),
},
{
- description: "ok response: new leaf",
- rsp: makeTrillianQueueLeafResponse(t, testPackage, testdata.Ed25519Vk, testdata.Ed25519Sk, false),
+ description: "valid: gRPC status: ok",
+ rsp: testdata.DefaultTQlr(t, false),
},
} {
- if err := checkQueueLeaf(table.rsp, table.err); (err != nil) != table.wantErr {
- t.Errorf("got error %v, but wanted error %v in test %q", err, table.wantErr, table.description)
+ err := checkQueueLeaf(table.rsp, table.err)
+ if got, want := err != nil, table.wantErr; got != want {
+ t.Errorf("got error %v but wanted %v in test %q", got, want, table.description)
}
}
}
@@ -51,101 +50,90 @@ func TestCheckQueueLeaf(t *testing.T) {
func TestCheckGetLeavesByRange(t *testing.T) {
for _, table := range []struct {
description string
- req *GetEntriesRequest
+ req *types.GetEntriesV1
rsp *trillian.GetLeavesByRangeResponse
err error
wantErr bool
}{
{
- description: "bad response: trillian error",
- req: &GetEntriesRequest{Start: 0, End: 1},
+ description: "invalid: no Trillian response: error",
+ req: &types.GetEntriesV1{Start: 0, End: 1},
err: fmt.Errorf("backend error"),
wantErr: true,
},
{
- description: "bad response: empty",
- req: &GetEntriesRequest{Start: 0, End: 1},
+ description: "invalid: no Trillian response: nil",
+ req: &types.GetEntriesV1{Start: 0, End: 1},
wantErr: true,
},
{
- description: "bad response: no leaves",
- req: &GetEntriesRequest{Start: 0, End: 1},
+ description: "invalid: bad Trillian response: no leaves",
+ req: &types.GetEntriesV1{Start: 0, End: 1},
rsp: func(rsp *trillian.GetLeavesByRangeResponse) *trillian.GetLeavesByRangeResponse {
rsp.Leaves = nil
return rsp
- }(makeTrillianGetLeavesByRangeResponse(t, 0, 1, testPackage, testdata.Ed25519Vk, testdata.Ed25519Sk)),
+ }(testdata.DefaultTGlbrr(t, 0, 1)),
wantErr: true,
},
{
- description: "bad response: no signed log root",
- req: &GetEntriesRequest{Start: 0, End: 1},
+ description: "invalid: bad Trillian response: no signed log root",
+ req: &types.GetEntriesV1{Start: 0, End: 1},
rsp: func(rsp *trillian.GetLeavesByRangeResponse) *trillian.GetLeavesByRangeResponse {
rsp.SignedLogRoot = nil
return rsp
- }(makeTrillianGetLeavesByRangeResponse(t, 0, 1, testPackage, testdata.Ed25519Vk, testdata.Ed25519Sk)),
+ }(testdata.DefaultTGlbrr(t, 0, 1)),
wantErr: true,
},
{
- description: "bad response: no log root",
- req: &GetEntriesRequest{Start: 0, End: 1},
+ description: "invalid: bad Trillian response: no log root",
+ req: &types.GetEntriesV1{Start: 0, End: 1},
rsp: func(rsp *trillian.GetLeavesByRangeResponse) *trillian.GetLeavesByRangeResponse {
rsp.SignedLogRoot.LogRoot = nil
return rsp
- }(makeTrillianGetLeavesByRangeResponse(t, 0, 1, testPackage, testdata.Ed25519Vk, testdata.Ed25519Sk)),
+ }(testdata.DefaultTGlbrr(t, 0, 1)),
wantErr: true,
},
{
- description: "bad response: truncated root",
- req: &GetEntriesRequest{Start: 0, End: 1},
+ description: "invalid: bad Trillian response: truncated log root",
+ req: &types.GetEntriesV1{Start: 0, End: 1},
rsp: func(rsp *trillian.GetLeavesByRangeResponse) *trillian.GetLeavesByRangeResponse {
rsp.SignedLogRoot.LogRoot = rsp.SignedLogRoot.LogRoot[1:]
return rsp
- }(makeTrillianGetLeavesByRangeResponse(t, 0, 1, testPackage, testdata.Ed25519Vk, testdata.Ed25519Sk)),
+ }(testdata.DefaultTGlbrr(t, 0, 1)),
wantErr: true,
},
{
- description: "bad response: too many leaves",
- req: &GetEntriesRequest{Start: 0, End: 1},
- rsp: makeTrillianGetLeavesByRangeResponse(t, 0, 2, testPackage, testdata.Ed25519Vk, testdata.Ed25519Sk),
+ description: "invalid: bad Trillian response: too many leaves",
+ req: &types.GetEntriesV1{Start: 0, End: 1},
+ rsp: testdata.DefaultTGlbrr(t, 0, 2),
wantErr: true,
},
{
- description: "bad response: start is not a valid index",
- req: &GetEntriesRequest{Start: int64(testTreeSize), End: int64(testTreeSize)},
- rsp: func(rsp *trillian.GetLeavesByRangeResponse) *trillian.GetLeavesByRangeResponse {
- rsp.SignedLogRoot = makeLatestSignedLogRootResponse(t, 0, testTreeSize, testNodeHash).SignedLogRoot
- return rsp
- }(makeTrillianGetLeavesByRangeResponse(t, int64(testTreeSize)-1, int64(testTreeSize)-1, testPackage, testdata.Ed25519Vk, testdata.Ed25519Sk)),
- wantErr: true,
- },
- {
- description: "bad response: invalid leaf indices",
- req: &GetEntriesRequest{Start: 10, End: 11},
- rsp: makeTrillianGetLeavesByRangeResponse(t, 11, 12, testPackage, testdata.Ed25519Vk, testdata.Ed25519Sk),
+ description: "invalid: bad Trillian response: start is not a valid index",
+ req: &types.GetEntriesV1{Start: 10, End: 10},
+ rsp: testdata.DefaultTGlbrr(t, 9, 9),
wantErr: true,
},
{
- description: "ok response: interval refers to the latest leaf",
- req: &GetEntriesRequest{Start: int64(testTreeSize) - 1, End: int64(testTreeSize) - 1},
- rsp: func(rsp *trillian.GetLeavesByRangeResponse) *trillian.GetLeavesByRangeResponse {
- rsp.SignedLogRoot = makeLatestSignedLogRootResponse(t, 0, testTreeSize, testNodeHash).SignedLogRoot
- return rsp
- }(makeTrillianGetLeavesByRangeResponse(t, int64(testTreeSize)-1, int64(testTreeSize)-1, testPackage, testdata.Ed25519Vk, testdata.Ed25519Sk)),
+ description: "invalid: bad Trillian response: invalid leaf indices",
+ req: &types.GetEntriesV1{Start: 10, End: 11},
+ rsp: testdata.DefaultTGlbrr(t, 11, 12),
+ wantErr: true,
},
{
- description: "ok response: a bunch of leaves",
- req: &GetEntriesRequest{Start: 10, End: 20},
- rsp: makeTrillianGetLeavesByRangeResponse(t, 10, 20, testPackage, testdata.Ed25519Vk, testdata.Ed25519Sk),
+ description: "valid",
+ req: &types.GetEntriesV1{Start: 10, End: 20},
+ rsp: testdata.DefaultTGlbrr(t, 10, 20),
},
} {
- if _, err := checkGetLeavesByRange(table.req, table.rsp, table.err); (err != nil) != table.wantErr {
- t.Errorf("got error %v, but wanted error %v in test %q", err, table.wantErr, table.description)
+ err := checkGetLeavesByRange(table.req, table.rsp, table.err)
+ if got, want := err != nil, table.wantErr; got != want {
+ t.Errorf("got error %v but wanted %v in test %q", got, want, table.description)
}
}
}
func TestCheckGetInclusionProofByHash(t *testing.T) {
- lp := makeTestLogParameters(t, nil)
for _, table := range []struct {
description string
rsp *trillian.GetInclusionProofByHashResponse
@@ -153,16 +141,16 @@ func TestCheckGetInclusionProofByHash(t *testing.T) {
wantErr bool
}{
{
- description: "bad response: trillian error",
+ description: "invalid: no Trillian response: error",
err: fmt.Errorf("backend failure"),
wantErr: true,
},
{
- description: "bad response: empty",
+ description: "invalid: no Trillian response: nil",
wantErr: true,
},
{
- description: "bad response: no proofs",
+ description: "invalid: bad Trillian response: no proofs",
rsp: &trillian.GetInclusionProofByHashResponse{},
wantErr: true,
},
@@ -171,27 +159,30 @@ func TestCheckGetInclusionProofByHash(t *testing.T) {
rsp: func(rsp *trillian.GetInclusionProofByHashResponse) *trillian.GetInclusionProofByHashResponse {
rsp.Proof[0] = nil
return rsp
- }(makeTrillianGetInclusionProofByHashResponse(t, int64(testIndex), testProof)),
+ }(testdata.DefaultTGipbhr(t)),
wantErr: true,
},
{
description: "bad response: proof with invalid node hash",
- rsp: makeTrillianGetInclusionProofByHashResponse(t, int64(testIndex), [][]byte{make([]byte, testHashLen-1)}),
- wantErr: true,
+ rsp: func(rsp *trillian.GetInclusionProofByHashResponse) *trillian.GetInclusionProofByHashResponse {
+ rsp.Proof[0].Hashes = append(rsp.Proof[0].Hashes, make([]byte, 0))
+ return rsp
+ }(testdata.DefaultTGipbhr(t)),
+ wantErr: true,
},
{
- description: "ok response",
- rsp: makeTrillianGetInclusionProofByHashResponse(t, int64(testIndex), testProof),
+ description: "valid",
+ rsp: testdata.DefaultTGipbhr(t),
},
} {
- if err := checkGetInclusionProofByHash(lp, table.rsp, table.err); (err != nil) != table.wantErr {
- t.Errorf("got error %v, but wanted error %v in test %q", err, table.wantErr, table.description)
+ err := checkGetInclusionProofByHash(newLogParameters(t, nil), table.rsp, table.err)
+ if got, want := err != nil, table.wantErr; got != want {
+ t.Errorf("got error %v but wanted %v in test %q", got, want, table.description)
}
}
}
func TestCheckGetConsistencyProof(t *testing.T) {
- lp := makeTestLogParameters(t, nil)
for _, table := range []struct {
description string
rsp *trillian.GetConsistencyProofResponse
@@ -199,37 +190,40 @@ func TestCheckGetConsistencyProof(t *testing.T) {
wantErr bool
}{
{
- description: "bad response: trillian error",
+ description: "invalid: no Trillian response: error",
err: fmt.Errorf("backend failure"),
wantErr: true,
},
{
- description: "bad response: empty",
+ description: "invalid: no Trillian response: nil",
wantErr: true,
},
{
- description: "bad response: no proof",
+ description: "invalid: bad Trillian response: no proof",
rsp: &trillian.GetConsistencyProofResponse{},
wantErr: true,
},
{
- description: "bad response: proof with invalid node hash",
- rsp: makeTrillianGetConsistencyProofResponse(t, [][]byte{make([]byte, testHashLen-1)}),
- wantErr: true,
+ description: "invalid: bad Trillian response: proof with invalid node hash",
+ rsp: func(rsp *trillian.GetConsistencyProofResponse) *trillian.GetConsistencyProofResponse {
+ rsp.Proof.Hashes = append(rsp.Proof.Hashes, make([]byte, 0))
+ return rsp
+ }(testdata.DefaultTGcpr(t)),
+ wantErr: true,
},
{
- description: "ok response",
- rsp: makeTrillianGetConsistencyProofResponse(t, testProof),
+ description: "valid",
+ rsp: testdata.DefaultTGcpr(t),
},
} {
- if err := checkGetConsistencyProof(lp, table.rsp, table.err); (err != nil) != table.wantErr {
- t.Errorf("got error %v, but wanted error %v in test %q", err, table.wantErr, table.description)
+ err := checkGetConsistencyProof(newLogParameters(t, nil), table.rsp, table.err)
+ if got, want := err != nil, table.wantErr; got != want {
+ t.Errorf("got error %v but wanted %v in test %q", got, want, table.description)
}
}
}
func TestCheckGetLatestSignedLogRoot(t *testing.T) {
- lp := makeTestLogParameters(t, nil)
for _, table := range []struct {
description string
rsp *trillian.GetLatestSignedLogRootResponse
@@ -237,160 +231,52 @@ func TestCheckGetLatestSignedLogRoot(t *testing.T) {
wantErr bool
}{
{
- description: "bad trillian response: error",
+ description: "invalid: no Trillian response: error",
err: fmt.Errorf("backend failure"),
wantErr: true,
},
{
- description: "bad trillian response: empty",
+ description: "invalid: no Trillian response: nil",
wantErr: true,
},
{
- description: "bad trillian response: no signed log root",
- rsp: &trillian.GetLatestSignedLogRootResponse{SignedLogRoot: nil},
- wantErr: true,
+ description: "invalid: bad Trillian response: no signed log root",
+ rsp: func(rsp *trillian.GetLatestSignedLogRootResponse) *trillian.GetLatestSignedLogRootResponse {
+ rsp.SignedLogRoot = nil
+ return rsp
+ }(testdata.DefaultTSlr(t)),
+ wantErr: true,
},
{
- description: "bad trillian response: no log root",
+ description: "invalid: bad Trillian response: no log root",
rsp: func(rsp *trillian.GetLatestSignedLogRootResponse) *trillian.GetLatestSignedLogRootResponse {
rsp.SignedLogRoot.LogRoot = nil
return rsp
- }(makeLatestSignedLogRootResponse(t, 0, 0, testNodeHash)),
+ }(testdata.DefaultTSlr(t)),
wantErr: true,
},
{
- description: "bad trillian response: truncated log root",
+ description: "invalid: bad Trillian response: truncated log root",
rsp: func(rsp *trillian.GetLatestSignedLogRootResponse) *trillian.GetLatestSignedLogRootResponse {
rsp.SignedLogRoot.LogRoot = rsp.SignedLogRoot.LogRoot[1:]
return rsp
- }(makeLatestSignedLogRootResponse(t, 0, 0, testNodeHash)),
+ }(testdata.DefaultTSlr(t)),
wantErr: true,
},
{
- description: "bad trillian response: invalid root hash size",
- rsp: makeLatestSignedLogRootResponse(t, 0, 0, make([]byte, testHashLen-1)),
+ description: "invalid: bad Trillian response: truncated root hash",
+ rsp: testdata.Tslr(t, testdata.Tlr(t, testdata.TreeSize, testdata.Timestamp, make([]byte, 31))),
wantErr: true,
},
{
- description: "ok response",
- rsp: makeLatestSignedLogRootResponse(t, 0, 0, testNodeHash),
+ description: "valid",
+ rsp: testdata.DefaultTSlr(t),
},
} {
- var lr types.LogRootV1
- if err := checkGetLatestSignedLogRoot(lp, table.rsp, table.err, &lr); (err != nil) != table.wantErr {
- t.Errorf("got error %v, but wanted error %v in test %q", err, table.wantErr, table.description)
+ var lr ttypes.LogRootV1
+ err := checkGetLatestSignedLogRoot(newLogParameters(t, nil), table.rsp, table.err, &lr)
+ if got, want := err != nil, table.wantErr; got != want {
+ t.Errorf("got error %v but wanted %v in test %q", got, want, table.description)
}
}
}
-
-// makeTrillianQueueLeafResponse creates a valid trillian QueueLeafResponse
-// for a package `name` where the checksum is all zeros (32 bytes). Namespace
-// is based on vk and sk (ed25519).
-//
-// Note: MerkleLeafHash and LeafIdentityHash are unset (not used by stfe).
-func makeTrillianQueueLeafResponse(t *testing.T, name, vk, sk []byte, dupCode bool) *trillian.QueueLeafResponse {
- t.Helper()
- leaf, signature := mustMakeEd25519ChecksumV1(t, name, make([]byte, 32), vk, sk)
- s := status.New(codes.OK, "ok").Proto()
- if dupCode {
- s = status.New(codes.AlreadyExists, "duplicate").Proto()
- }
- return &trillian.QueueLeafResponse{
- QueuedLeaf: &trillian.QueuedLogLeaf{
- Leaf: &trillian.LogLeaf{
- MerkleLeafHash: nil, // not used by stfe
- LeafValue: leaf,
- ExtraData: signature,
- LeafIndex: 0, // not applicable (log is not pre-ordered)
- LeafIdentityHash: nil, // not used by stfe
- },
- Status: s,
- },
- }
-}
-
-// makeTrillianGetInclusionProofByHashResponse populates a get-proof-by-hash
-// response.
-//
-// Note: SignedLogRoot is unset (not used by stfe).
-func makeTrillianGetInclusionProofByHashResponse(t *testing.T, index int64, path [][]byte) *trillian.GetInclusionProofByHashResponse {
- t.Helper()
- return &trillian.GetInclusionProofByHashResponse{
- Proof: []*trillian.Proof{
- &trillian.Proof{
- LeafIndex: index,
- Hashes: path,
- },
- },
- SignedLogRoot: nil,
- }
-}
-
-// makeTrillianGetConsistencyProofResponse populates a get-consistency response.
-//
-// Note: LeafIndex is not applicable for a consistency proof (0), and
-// SignedLogRoot is unset (not used by stfe).
-func makeTrillianGetConsistencyProofResponse(t *testing.T, path [][]byte) *trillian.GetConsistencyProofResponse {
- t.Helper()
- return &trillian.GetConsistencyProofResponse{
- Proof: &trillian.Proof{
- LeafIndex: 0,
- Hashes: path,
- },
- SignedLogRoot: nil,
- }
-}
-
-// makeTrillianGetLeavesByRangeResponse creates a range of leaves [start,end]
-// such that the package is `name`_<index> and the checksum is all zeros (32
-// bytes). An Ed25519 namespace is used based on vk and sk.
-//
-// Note: MerkleLeafHash and LeafIdentityHash are unset (not used by stfe).
-func makeTrillianGetLeavesByRangeResponse(t *testing.T, start, end int64, name, vk, sk []byte) *trillian.GetLeavesByRangeResponse {
- t.Helper()
- leaves := make([]*trillian.LogLeaf, 0, end-start+1)
- for i, n := start, end+1; i < n; i++ {
- leaf, signature := mustMakeEd25519ChecksumV1(t, append(name, []byte(fmt.Sprintf("_%d", i))...), make([]byte, 32), vk, sk)
- leaves = append(leaves, &trillian.LogLeaf{
- MerkleLeafHash: nil,
- LeafValue: leaf,
- ExtraData: signature,
- LeafIndex: i,
- LeafIdentityHash: nil,
- })
- }
- return &trillian.GetLeavesByRangeResponse{
- Leaves: leaves,
- SignedLogRoot: makeLatestSignedLogRootResponse(t, 0, uint64(end)+1, make([]byte, 32)).SignedLogRoot,
- }
-}
-
-// makeTrillianLogRoot: docdoc
-func makeTrillianLogRoot(t *testing.T, timestamp, size uint64, hash []byte) *types.LogRootV1 {
- t.Helper()
- return &types.LogRootV1{
- TreeSize: size,
- RootHash: hash,
- TimestampNanos: timestamp,
- Revision: 0, // not used by stfe
- Metadata: nil, // not used by stfe
- }
-}
-
-// makeLatestSignedLogRootResponse creates a new trillian STH. Revision,
-// Metadata, Proof, KeyHint, and LogRootSignature are unsset.
-func makeLatestSignedLogRootResponse(t *testing.T, timestamp, size uint64, hash []byte) *trillian.GetLatestSignedLogRootResponse {
- t.Helper()
- rootBytes, err := makeTrillianLogRoot(t, timestamp, size, hash).MarshalBinary()
- if err != nil {
- t.Fatalf("failed to marshal root in test: %v", err)
- }
- return &trillian.GetLatestSignedLogRootResponse{
- SignedLogRoot: &trillian.SignedLogRoot{
- KeyHint: nil, // not used by stfe
- LogRoot: rootBytes,
- LogRootSignature: nil, // not used by stfe
- },
- Proof: nil, // not used by stfe
- }
-}