aboutsummaryrefslogtreecommitdiff
path: root/pkg/db/trillian.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/db/trillian.go')
-rw-r--r--pkg/db/trillian.go194
1 files changed, 0 insertions, 194 deletions
diff --git a/pkg/db/trillian.go b/pkg/db/trillian.go
deleted file mode 100644
index 3147c8d..0000000
--- a/pkg/db/trillian.go
+++ /dev/null
@@ -1,194 +0,0 @@
-package db
-
-import (
- "context"
- "fmt"
- "time"
-
- "git.sigsum.org/sigsum-go/pkg/log"
- "git.sigsum.org/sigsum-go/pkg/requests"
- "git.sigsum.org/sigsum-go/pkg/types"
- "github.com/google/trillian"
- trillianTypes "github.com/google/trillian/types"
- "google.golang.org/grpc/codes"
-)
-
-// TrillianClient implements the Client interface for Trillian's gRPC backend
-type TrillianClient struct {
- // TreeID is a Merkle tree identifier that Trillian uses
- TreeID int64
-
- // GRPC is a Trillian gRPC client
- GRPC trillian.TrillianLogClient
-}
-
-func (c *TrillianClient) AddLeaf(ctx context.Context, req *requests.Leaf) error {
- leaf := types.Leaf{
- Statement: types.Statement{
- ShardHint: req.ShardHint,
- Checksum: *types.HashFn(req.Message[:]),
- },
- Signature: req.Signature,
- KeyHash: *types.HashFn(req.PublicKey[:]),
- }
- serialized := leaf.ToBinary()
-
- log.Debug("queueing leaf request: %x", types.LeafHash(serialized))
- rsp, err := c.GRPC.QueueLeaf(ctx, &trillian.QueueLeafRequest{
- LogId: c.TreeID,
- Leaf: &trillian.LogLeaf{
- LeafValue: serialized,
- },
- })
- if err != nil {
- return fmt.Errorf("backend failure: %v", err)
- }
- if rsp == nil {
- return fmt.Errorf("no response")
- }
- if rsp.QueuedLeaf == nil {
- return fmt.Errorf("no queued leaf")
- }
- if codes.Code(rsp.QueuedLeaf.GetStatus().GetCode()) == codes.AlreadyExists {
- return fmt.Errorf("leaf is already queued or included")
- }
- return nil
-}
-
-func (c *TrillianClient) GetTreeHead(ctx context.Context) (*types.TreeHead, error) {
- rsp, err := c.GRPC.GetLatestSignedLogRoot(ctx, &trillian.GetLatestSignedLogRootRequest{
- LogId: c.TreeID,
- })
- if err != nil {
- return nil, fmt.Errorf("backend failure: %v", err)
- }
- if rsp == nil {
- return nil, fmt.Errorf("no response")
- }
- if rsp.SignedLogRoot == nil {
- return nil, fmt.Errorf("no signed log root")
- }
- if rsp.SignedLogRoot.LogRoot == nil {
- return nil, fmt.Errorf("no log root")
- }
- var r trillianTypes.LogRootV1
- if err := r.UnmarshalBinary(rsp.SignedLogRoot.LogRoot); err != nil {
- return nil, fmt.Errorf("no log root: unmarshal failed: %v", err)
- }
- if len(r.RootHash) != types.HashSize {
- return nil, fmt.Errorf("unexpected hash length: %d", len(r.RootHash))
- }
- return treeHeadFromLogRoot(&r), nil
-}
-
-func (c *TrillianClient) GetConsistencyProof(ctx context.Context, req *requests.ConsistencyProof) (*types.ConsistencyProof, error) {
- rsp, err := c.GRPC.GetConsistencyProof(ctx, &trillian.GetConsistencyProofRequest{
- LogId: c.TreeID,
- FirstTreeSize: int64(req.OldSize),
- SecondTreeSize: int64(req.NewSize),
- })
- if err != nil {
- return nil, fmt.Errorf("backend failure: %v", err)
- }
- if rsp == nil {
- return nil, fmt.Errorf("no response")
- }
- if rsp.Proof == nil {
- return nil, fmt.Errorf("no consistency proof")
- }
- if len(rsp.Proof.Hashes) == 0 {
- return nil, fmt.Errorf("not a consistency proof: empty")
- }
- path, err := nodePathFromHashes(rsp.Proof.Hashes)
- if err != nil {
- return nil, fmt.Errorf("not a consistency proof: %v", err)
- }
- return &types.ConsistencyProof{
- OldSize: req.OldSize,
- NewSize: req.NewSize,
- Path: path,
- }, nil
-}
-
-func (c *TrillianClient) GetInclusionProof(ctx context.Context, req *requests.InclusionProof) (*types.InclusionProof, error) {
- 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 *TrillianClient) GetLeaves(ctx context.Context, req *requests.Leaves) (*types.Leaves, error) {
- rsp, err := c.GRPC.GetLeavesByRange(ctx, &trillian.GetLeavesByRangeRequest{
- LogId: c.TreeID,
- StartIndex: int64(req.StartSize),
- Count: int64(req.EndSize-req.StartSize) + 1,
- })
- if err != nil {
- return nil, fmt.Errorf("backend failure: %v", err)
- }
- if rsp == nil {
- return nil, fmt.Errorf("no response")
- }
- if got, want := len(rsp.Leaves), int(req.EndSize-req.StartSize+1); got != want {
- return nil, fmt.Errorf("unexpected number of leaves: %d", got)
- }
- var list types.Leaves = make([]types.Leaf, 0, len(rsp.Leaves))
- for i, leaf := range rsp.Leaves {
- leafIndex := int64(req.StartSize + uint64(i))
- if leafIndex != leaf.LeafIndex {
- return nil, fmt.Errorf("unexpected leaf(%d): got index %d", leafIndex, leaf.LeafIndex)
- }
-
- var l types.Leaf
- if err := l.FromBinary(leaf.LeafValue); err != nil {
- return nil, fmt.Errorf("unexpected leaf(%d): %v", leafIndex, err)
- }
- list = append(list[:], l)
- }
- return &list, nil
-}
-
-func treeHeadFromLogRoot(lr *trillianTypes.LogRootV1) *types.TreeHead {
- th := types.TreeHead{
- Timestamp: uint64(time.Now().Unix()),
- TreeSize: uint64(lr.TreeSize),
- }
- copy(th.RootHash[:], lr.RootHash)
- return &th
-}
-
-func nodePathFromHashes(hashes [][]byte) ([]types.Hash, error) {
- path := make([]types.Hash, len(hashes))
- for i := 0; i < len(hashes); i++ {
- if len(hashes[i]) != types.HashSize {
- return nil, fmt.Errorf("unexpected hash length: %v", len(hashes[i]))
- }
-
- copy(path[i][:], hashes[i])
- }
- return path, nil
-}