github.com/google/trillian-examples@v0.0.0-20240520080811-0d40d35cef0e/binary_transparency/firmware/internal/client/utils.go (about)

     1  // Copyright 2020 Google LLC. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package client
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"time"
    21  
    22  	"github.com/golang/glog"
    23  	"github.com/google/trillian-examples/binary_transparency/firmware/api"
    24  	"github.com/transparency-dev/merkle/proof"
    25  	"github.com/transparency-dev/merkle/rfc6962"
    26  )
    27  
    28  // AwaitInclusion waits for the specified statement s to be included into the log and then
    29  // returns the checkpoint under which it was found to be present, along with valid consistency and inclusion proofs.
    30  func AwaitInclusion(ctx context.Context, c *ReadonlyClient, cp api.LogCheckpoint, s []byte) (api.LogCheckpoint, api.ConsistencyProof, api.InclusionProof, error) {
    31  	lh := rfc6962.DefaultHasher
    32  	for {
    33  		select {
    34  		case <-time.After(1 * time.Second):
    35  			//
    36  		case <-ctx.Done():
    37  			return api.LogCheckpoint{}, api.ConsistencyProof{}, api.InclusionProof{}, ctx.Err()
    38  		}
    39  
    40  		newCP, err := c.GetCheckpoint()
    41  		if err != nil {
    42  			return api.LogCheckpoint{}, api.ConsistencyProof{}, api.InclusionProof{}, err
    43  		}
    44  
    45  		if newCP.Size <= cp.Size {
    46  			glog.V(1).Info("Waiting for tree to integrate new leaves")
    47  			continue
    48  		}
    49  		var consistency api.ConsistencyProof
    50  		if cp.Size > 0 {
    51  			cproof, err := c.GetConsistencyProof(api.GetConsistencyRequest{From: cp.Size, To: newCP.Size})
    52  			if err != nil {
    53  				glog.Warningf("Received error while fetching consistency proof: %q", err)
    54  				continue
    55  			}
    56  			consistency = *cproof
    57  			if err := proof.VerifyConsistency(lh, cp.Size, newCP.Size, consistency.Proof, cp.Hash, newCP.Hash); err != nil {
    58  				// Whoa Nelly, this is bad - bail!
    59  				glog.Warning("Invalid consistency proof received!")
    60  				return *newCP, consistency, api.InclusionProof{}, fmt.Errorf("invalid inclusion proof received: %w", err)
    61  			}
    62  			glog.Infof("Consistency proof between %d and %d verified", cp.Size, newCP.Size)
    63  		}
    64  		cp = *newCP
    65  
    66  		ip, err := c.GetInclusion(s, cp)
    67  		if err != nil {
    68  			glog.Warningf("Received error while fetching inclusion proof: %q", err)
    69  			continue
    70  		}
    71  		if err := proof.VerifyInclusion(lh, ip.LeafIndex, cp.Size, lh.HashLeaf(s), ip.Proof, cp.Hash); err != nil {
    72  			// Whoa Nelly, this is bad - bail!
    73  			glog.Warning("Invalid inclusion proof received!")
    74  			return cp, consistency, ip, fmt.Errorf("invalid inclusion proof received: %w", err)
    75  		}
    76  
    77  		glog.Infof("Inclusion proof for leafhash 0x%x verified", lh)
    78  		return cp, consistency, ip, nil
    79  	}
    80  	// unreachable
    81  }