func (c *LogClient) GetProofByHash(ctx context.Context, hash []byte, treeSize uint64) (*ct.GetProofByHashResponse, error) {
	b64Hash := base64.StdEncoding.EncodeToString(hash)
	base10 := 10
	params := map[string]string{
		"tree_size": strconv.FormatUint(treeSize, base10),
		"hash":      b64Hash,
	}
	var resp ct.GetProofByHashResponse
	if _, _, err := c.GetAndParse(ctx, ct.GetProofByHashPath, params, &resp); err != nil {
		return nil, err
	}
	return &resp, nil
}
GetProofByHash returns an audit path for the hash of an SCT.
package client
import (
	"context"
	"encoding/base64"
	"fmt"
	"net/http"
	"strconv"
	ct "github.com/google/certificate-transparency-go"
	"github.com/google/certificate-transparency-go/jsonclient"
	"github.com/google/certificate-transparency-go/tls"
)
type LogClient struct {
	jsonclient.JSONClient
}
type CheckLogClient interface {
	BaseURI() string
	GetSTH(context.Context) (*ct.SignedTreeHead, error)
	GetSTHConsistency(ctx context.Context, first, second uint64) ([][]byte, error)
	GetProofByHash(ctx context.Context, hash []byte, treeSize uint64) (*ct.GetProofByHashResponse, error)
}
func New(uri string, hc *http.Client, opts jsonclient.Options) (*LogClient, error) {
	logClient, err := jsonclient.New(uri, hc, opts)
	if err != nil {
		return nil, err
	}
	return &LogClient{*logClient}, err
}
type RspError = jsonclient.RspError
func (c *LogClient) addChainWithRetry(ctx context.Context, ctype ct.LogEntryType, path string, chain []ct.ASN1Cert) (*ct.SignedCertificateTimestamp, error) {
	var resp ct.AddChainResponse
	var req ct.AddChainRequest
	for _, link := range chain {
		req.Chain = append(req.Chain, link.Data)
	}
	httpRsp, body, err := c.PostAndParseWithRetry(ctx, path, &req, &resp)
	if err != nil {
		return nil, err
	}
	var ds ct.DigitallySigned
	if rest, err := tls.Unmarshal(resp.Signature, &ds); err != nil {
		return nil, RspError{Err: err, StatusCode: httpRsp.StatusCode, Body: body}
	} else if len(rest) > 0 {
		return nil, RspError{
			Err:        fmt.Errorf("trailing data (%d bytes) after DigitallySigned", len(rest)),
			StatusCode: httpRsp.StatusCode,
			Body:       body,
		}
	}
	exts, err := base64.StdEncoding.DecodeString(resp.Extensions)
	if err != nil {
		return nil, RspError{
			Err:        fmt.Errorf("invalid base64 data in Extensions (%q): %v", resp.Extensions, err),
			StatusCode: httpRsp.StatusCode,
			Body:       body,
		}
	}
	var logID ct.LogID
	copy(logID.KeyID[:], resp.ID)
	sct := &ct.SignedCertificateTimestamp{
		SCTVersion: resp.SCTVersion,
		LogID:      logID,
		Timestamp:  resp.Timestamp,
		Extensions: ct.CTExtensions(exts),
		Signature:  ds,
	}
	if err := c.VerifySCTSignature(*sct, ctype, chain); err != nil {
		return nil, RspError{Err: err, StatusCode: httpRsp.StatusCode, Body: body}
	}
	return sct, nil
}
func (c *LogClient) AddChain(ctx context.Context, chain []ct.ASN1Cert) (*ct.SignedCertificateTimestamp, error) {
	return c.addChainWithRetry(ctx, ct.X509LogEntryType, ct.AddChainPath, chain)
}
func (c *LogClient) AddPreChain(ctx context.Context, chain []ct.ASN1Cert) (*ct.SignedCertificateTimestamp, error) {
	return c.addChainWithRetry(ctx, ct.PrecertLogEntryType, ct.AddPreChainPath, chain)
}
func (c *LogClient) GetSTH(ctx context.Context) (*ct.SignedTreeHead, error) {
	var resp ct.GetSTHResponse
	httpRsp, body, err := c.GetAndParse(ctx, ct.GetSTHPath, nil, &resp)
	if err != nil {
		return nil, err
	}
	sth, err := resp.ToSignedTreeHead()
	if err != nil {
		return nil, RspError{Err: err, StatusCode: httpRsp.StatusCode, Body: body}
	}
	if err := c.VerifySTHSignature(*sth); err != nil {
		return nil, RspError{Err: err, StatusCode: httpRsp.StatusCode, Body: body}
	}
	return sth, nil
}
func (c *LogClient) VerifySTHSignature(sth ct.SignedTreeHead) error {
	if c.Verifier == nil {
		return nil
	}
	return c.Verifier.VerifySTHSignature(sth)
}
func (c *LogClient) VerifySCTSignature(sct ct.SignedCertificateTimestamp, ctype ct.LogEntryType, certData []ct.ASN1Cert) error {
	if c.Verifier == nil {
		return nil
	}
	leaf, err := ct.MerkleTreeLeafFromRawChain(certData, ctype, sct.Timestamp)
	if err != nil {
		return fmt.Errorf("failed to build MerkleTreeLeaf: %v", err)
	}
	entry := ct.LogEntry{Leaf: *leaf}
	return c.Verifier.VerifySCTSignature(sct, entry)
}
func (c *LogClient) GetSTHConsistency(ctx context.Context, first, second uint64) ([][]byte, error) {
	base10 := 10
	params := map[string]string{
		"first":  strconv.FormatUint(first, base10),
		"second": strconv.FormatUint(second, base10),
	}
	var resp ct.GetSTHConsistencyResponse
	if _, _, err := c.GetAndParse(ctx, ct.GetSTHConsistencyPath, params, &resp); err != nil {
		return nil, err
	}
	return resp.Consistency, nil
}