diff options
Diffstat (limited to 'trillian')
| -rw-r--r-- | trillian/client.go | 29 | ||||
| -rw-r--r-- | trillian/client_test.go | 113 | 
2 files changed, 139 insertions, 3 deletions
| diff --git a/trillian/client.go b/trillian/client.go index 7b8a00a..cbeb1ca 100644 --- a/trillian/client.go +++ b/trillian/client.go @@ -108,7 +108,34 @@ func (c *Client) GetConsistencyProof(ctx context.Context, req *types.Consistency  }  func (c *Client) GetInclusionProof(ctx context.Context, req *types.InclusionProofRequest) (*types.InclusionProof, error) { -	return nil, fmt.Errorf("TODO") +	rsp, err := c.GRPC.GetInclusionProofByHash(ctx, &trillian.GetInclusionProofByHashRequest{ +		LogId:           c.TreeID, +		LeafHash:        req.LeafHash[:], +		TreeSize:        int64(req.TreeSize), +		OrderBySequence: true, +	}) +	if err != nil { +		return nil, fmt.Errorf("backend failure: %v", err) +	} +	if rsp == nil { +		return nil, fmt.Errorf("no response") +	} +	if len(rsp.Proof) != 1 { +		return nil, fmt.Errorf("bad proof count: %d", len(rsp.Proof)) +	} +	proof := rsp.Proof[0] +	if len(proof.Hashes) == 0 { +		return nil, fmt.Errorf("not an inclusion proof: empty") +	} +	path, err := nodePathFromHashes(proof.Hashes) +	if err != nil { +		return nil, fmt.Errorf("not an inclusion proof: %v", err) +	} +	return &types.InclusionProof{ +		TreeSize:  req.TreeSize, +		LeafIndex: uint64(proof.LeafIndex), +		Path:      path, +	}, nil  }  func (c *Client) GetLeaves(ctx context.Context, req *types.LeavesRequest) (*types.LeafList, error) { diff --git a/trillian/client_test.go b/trillian/client_test.go index 1d1c16f..001d1dc 100644 --- a/trillian/client_test.go +++ b/trillian/client_test.go @@ -287,5 +287,114 @@ func TestGetConsistencyProof(t *testing.T) {  	}  } -func TestGetInclusionProof(t *testing.T) {} -func TestGetLeaves(t *testing.T)         {} +func TestGetInclusionProof(t *testing.T) { +	req := &types.InclusionProofRequest{ +		TreeSize: 4, +		LeafHash: &[types.HashSize]byte{}, +	} +	for _, table := range []struct { +		description string +		req         *types.InclusionProofRequest +		rsp         *trillian.GetInclusionProofByHashResponse +		err         error +		wantErr     bool +		wantProof   *types.InclusionProof +	}{ +		{ +			description: "invalid: backend failure", +			req:         req, +			err:         fmt.Errorf("something went wrong"), +			wantErr:     true, +		}, +		{ +			description: "invalid: no response", +			req:         req, +			wantErr:     true, +		}, +		{ +			description: "invalid: bad proof count", +			req:         req, +			rsp: &trillian.GetInclusionProofByHashResponse{ +				Proof: []*trillian.Proof{ +					&trillian.Proof{}, +					&trillian.Proof{}, +				}, +			}, +			wantErr: true, +		}, +		{ +			description: "invalid: not an inclusion proof (1/2)", +			req:         req, +			rsp: &trillian.GetInclusionProofByHashResponse{ +				Proof: []*trillian.Proof{ +					&trillian.Proof{ +						LeafIndex: 1, +						Hashes:    [][]byte{}, +					}, +				}, +			}, +			wantErr: true, +		}, +		{ +			description: "invalid: not an inclusion proof (2/2)", +			req:         req, +			rsp: &trillian.GetInclusionProofByHashResponse{ +				Proof: []*trillian.Proof{ +					&trillian.Proof{ +						LeafIndex: 1, +						Hashes: [][]byte{ +							make([]byte, types.HashSize), +							make([]byte, types.HashSize+1), +						}, +					}, +				}, +			}, +			wantErr: true, +		}, +		{ +			description: "valid", +			req:         req, +			rsp: &trillian.GetInclusionProofByHashResponse{ +				Proof: []*trillian.Proof{ +					&trillian.Proof{ +						LeafIndex: 1, +						Hashes: [][]byte{ +							make([]byte, types.HashSize), +							make([]byte, types.HashSize), +						}, +					}, +				}, +			}, +			wantProof: &types.InclusionProof{ +				TreeSize:  4, +				LeafIndex: 1, +				Path: []*[types.HashSize]byte{ +					&[types.HashSize]byte{}, +					&[types.HashSize]byte{}, +				}, +			}, +		}, +	} { +		// Run deferred functions at the end of each iteration +		func() { +			ctrl := gomock.NewController(t) +			defer ctrl.Finish() +			grpc := mockclient.NewMockTrillianLogClient(ctrl) +			grpc.EXPECT().GetInclusionProofByHash(gomock.Any(), gomock.Any()).Return(table.rsp, table.err) +			client := Client{GRPC: grpc} + +			proof, err := client.GetInclusionProof(context.Background(), table.req) +			if got, want := err != nil, table.wantErr; got != want { +				t.Errorf("got error %v but wanted %v in test %q: %v", got, want, table.description, err) +			} +			if err != nil { +				return +			} +			if got, want := proof, table.wantProof; !reflect.DeepEqual(got, want) { +				t.Errorf("got proof\n\t%v\nbut wanted\n\t%v\nin test %q", got, want, table.description) +			} +		}() +	} +} + +func TestGetLeaves(t *testing.T) {} | 
