Search for a specific version of an identifier
Some checks failed
CI / test (push) Has been cancelled

This commit is contained in:
Katherine 2025-10-29 09:59:56 -04:00 committed by GitHub
parent e1df58749d
commit e5a45343df
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 633 additions and 355 deletions

View File

@ -31,7 +31,7 @@ func handleDistinguished(client pb.KeyTransparencyQueryServiceClient) {
if *configFile == "" {
p.Printf("Verification skipped\n")
} else {
if err := transparency.VerifySearch(newStore(), createTreeSearchRequest([]byte("distinguished")), createTreeSearchResponse(res.Distinguished, res.TreeHead)); err != nil {
if err := transparency.VerifySearch(newStore(), createTreeSearchRequest([]byte("distinguished"), nil), createTreeSearchResponse(res.Distinguished, res.TreeHead)); err != nil {
p.Printf("Verification failed: %v\n", err)
} else {
p.Printf("Verification successful\n")

View File

@ -32,11 +32,14 @@ var (
testServerAddr = flag.String("test-addr", "localhost:8081", "Address of test server.")
configFile = flag.String("config", "", "(Optional) Location of server config file.")
usernameHash = flag.String("username-hash", "", "Base64url encoded username hash")
e164 = flag.String("e164", "", "E164-formatted phone number. Must be preceded with a '+'. E.g. +14155550101")
uak = flag.String("uak", "", "Standard base64 encoded unidentified access key")
timingNumSamples = flag.Int("num-samples", 5, "Number of samples to use for measuring timing of a query request")
timingSampleSize = flag.Int("sample-size", 100, "Number of requests per sample to use for measuring timing of a query request")
usernameHash = flag.String("username-hash", "", "Base64url encoded username hash")
e164 = flag.String("e164", "", "E164-formatted phone number. Must be preceded with a '+'. E.g. +14155550101")
uak = flag.String("uak", "", "Standard base64 encoded unidentified access key")
aciVersionStr = flag.String("aci-version", "", "Which version of the provided ACI to search for")
e164VersionStr = flag.String("e164-version", "", "Which version of the provided E164 to search for")
usernameHashVersionStr = flag.String("username-hash-version", "", "Which version of the provided username hash to search for")
timingNumSamples = flag.Int("num-samples", 5, "Number of samples to use for measuring timing of a query request")
timingSampleSize = flag.Int("sample-size", 100, "Number of requests per sample to use for measuring timing of a query request")
last = flag.Int("last", -1, "(Optional) Size of tree when last observed, or -1 for none.")
)

View File

@ -7,6 +7,7 @@ package main
import (
"context"
"encoding/base64"
"github.com/signalapp/keytransparency/cmd/internal/util"
"github.com/signalapp/keytransparency/cmd/kt-server/pb"
@ -20,15 +21,25 @@ func constructSearchRequest(args QueryArgs) *pb.SearchRequest {
AciIdentityKey: args.AciIdentityKey,
Consistency: consistency(last),
}
if args.AciVersion != nil {
req.AciVersion = args.AciVersion
}
if args.E164 != "" {
req.E164SearchRequest = &pb.E164SearchRequest{
E164: &args.E164,
UnidentifiedAccessKey: args.UnidentifiedAccessKey,
}
if args.E164Version != nil {
req.E164Version = args.E164Version
}
}
if args.UsernameHash != nil {
req.UsernameHash = args.UsernameHash
if args.UsernameHashVersion != nil {
req.UsernameHashVersion = args.UsernameHashVersion
}
}
return req
}
@ -40,25 +51,28 @@ func handleSearch(client pb.KeyTransparencyQueryServiceClient) {
printFullTreeHead(res.TreeHead)
p.Printf("ACI search response: \n")
p.Printf("VRF: %x\n\n", res.Aci.VrfProof)
printSearchProof(res.Aci.Search)
p.Printf("Opening: %x\n", res.Aci.Opening)
p.Printf("Value: %x\n\n", res.Aci.Value.Value)
p.Printf("Value: %s\n\n", base64.StdEncoding.EncodeToString(res.Aci.Value.Value[1:]))
if res.E164 != nil {
p.Printf("E164 search response: \n")
p.Printf("VRF: %x\n\n", res.E164.VrfProof)
printSearchProof(res.E164.Search)
p.Printf("Opening: %x\n", res.E164.Opening)
p.Printf("Value: %x\n\n", res.E164.Value.Value)
p.Printf("Value: %x\n\n", res.E164.Value.Value[1:])
}
if res.UsernameHash != nil {
p.Printf("Username hash search response: \n")
p.Printf("VRF: %x\n\n", res.UsernameHash.VrfProof)
printSearchProof(res.UsernameHash.Search)
p.Printf("Opening: %x\n", res.UsernameHash.Opening)
p.Printf("Value: %x\n\n", res.UsernameHash.Value.Value)
p.Printf("Value: %x\n\n", res.UsernameHash.Value.Value[1:])
}
if *configFile == "" {
@ -74,20 +88,20 @@ func handleSearch(client pb.KeyTransparencyQueryServiceClient) {
}
allVerificationsSuccessful := true
if err := transparency.VerifySearch(newStore(), createIdentifierSearchRequest(util.AciPrefix, args.Aci), createTreeSearchResponse(res.Aci, res.TreeHead)); err != nil {
if err := transparency.VerifySearch(newStore(), createIdentifierSearchRequest(util.AciPrefix, args.Aci, args.AciVersion), createTreeSearchResponse(res.Aci, res.TreeHead)); err != nil {
p.Printf("ACI verification failed: %v\n", err)
allVerificationsSuccessful = false
}
if res.E164 != nil {
if err := transparency.VerifySearch(newStore(), createIdentifierSearchRequest(util.NumberPrefix, []byte(*e164)), createTreeSearchResponse(res.E164, res.TreeHead)); err != nil {
if err := transparency.VerifySearch(newStore(), createIdentifierSearchRequest(util.NumberPrefix, []byte(*e164), args.E164Version), createTreeSearchResponse(res.E164, res.TreeHead)); err != nil {
p.Printf("E164 verification failed: %v\n", err)
allVerificationsSuccessful = false
}
}
if res.UsernameHash != nil {
if err := transparency.VerifySearch(newStore(), createIdentifierSearchRequest(util.UsernameHashPrefix, args.UsernameHash), createTreeSearchResponse(res.UsernameHash, res.TreeHead)); err != nil {
if err := transparency.VerifySearch(newStore(), createIdentifierSearchRequest(util.UsernameHashPrefix, args.UsernameHash, args.UsernameHashVersion), createTreeSearchResponse(res.UsernameHash, res.TreeHead)); err != nil {
p.Printf("Username hash verification failed: %v\n", err)
allVerificationsSuccessful = false
}
@ -98,15 +112,19 @@ func handleSearch(client pb.KeyTransparencyQueryServiceClient) {
}
}
func createIdentifierSearchRequest(prefix byte, identifier []byte) *tpb.TreeSearchRequest {
return createTreeSearchRequest(append([]byte{prefix}, identifier...))
func createIdentifierSearchRequest(prefix byte, identifier []byte, version *uint32) *tpb.TreeSearchRequest {
return createTreeSearchRequest(append([]byte{prefix}, identifier...), version)
}
func createTreeSearchRequest(key []byte) *tpb.TreeSearchRequest {
return &tpb.TreeSearchRequest{
func createTreeSearchRequest(key []byte, version *uint32) *tpb.TreeSearchRequest {
req := &tpb.TreeSearchRequest{
SearchKey: key,
Consistency: consistency(last),
}
if version != nil {
req.Version = version
}
return req
}
func createTreeSearchResponse(response *pb.CondensedTreeSearchResponse, treeHead *tpb.FullTreeHead) *tpb.TreeSearchResponse {

View File

@ -11,6 +11,7 @@ import (
"fmt"
"log"
"os"
"strconv"
"time"
"github.com/google/uuid"
@ -21,10 +22,13 @@ import (
type QueryArgs struct {
Aci []byte
AciVersion *uint32
AciIdentityKey []byte
E164 string
E164Version *uint32
UnidentifiedAccessKey []byte
UsernameHash []byte
UsernameHashVersion *uint32
}
func extractQueryArgs(command string) QueryArgs {
@ -57,12 +61,19 @@ func extractQueryArgs(command string) QueryArgs {
checkErr("decoding base64url encoding for username hash", err)
}
aciVersion := parseVersion(aciVersionStr, "aci version")
e164Version := parseVersion(e164VersionStr, "e164 version")
usernameHashVersion := parseVersion(usernameHashVersionStr, "usernameHash version")
return QueryArgs{
aciBytes,
aciVersion,
aciIdentityKeyBytes,
*e164,
e164Version,
unidentifiedAccessKeyBytes,
usernameHashBytes,
usernameHashVersion,
}
}
@ -143,3 +154,16 @@ func checkErr(context string, err error) {
os.Exit(1)
}
}
func parseVersion(versionStr *string, argName string) *uint32 {
var version *uint32
if *versionStr != "" {
val, err := strconv.ParseUint(*versionStr, 10, 32)
if err != nil {
log.Fatalf("invalid %s: %v", argName, err)
}
v := uint32(val)
version = &v
}
return version
}

View File

@ -8,6 +8,7 @@ package main
import (
"context"
"crypto/subtle"
"fmt"
"math/rand"
"strings"
"time"
@ -155,9 +156,16 @@ func aciSearch(req *pb.SearchRequest, tree *transparency.Tree) (*tpb.FullTreeHea
aciResponse, err := tree.Search(&tpb.TreeSearchRequest{
SearchKey: append([]byte{util.AciPrefix}, req.Aci...),
Consistency: consistency,
Version: req.AciVersion,
})
metrics.IncrCounterWithLabels([]string{"search_requests", "aci"}, 1, []metrics.Label{{Name: "hasVersion", Value: fmt.Sprint(req.AciVersion != nil)}, grpcStatusLabel(err)})
if err != nil {
// There's no use case for distinguishing "not found" vs "permission denied"
// and consolidating prevents information leakage.
if grpcError, _ := status.FromError(err); grpcError.Code() == codes.NotFound {
err = status.Error(codes.PermissionDenied, "provided value does not match expected value")
}
return nil, nil, err
} else if len(aciResponse.Value.Value) < 2 || aciResponse.Value.Value[0] != 0 {
return nil, nil, status.Error(codes.Internal, "unexpected response value")
@ -175,10 +183,13 @@ func usernameHashSearch(req *pb.SearchRequest, tree *transparency.Tree) (*pb.Con
if len(req.UsernameHash) == 0 {
return nil, nil
}
usernameHashResponse, responseErr := tree.Search(&tpb.TreeSearchRequest{
SearchKey: append([]byte{util.UsernameHashPrefix}, req.UsernameHash...),
Consistency: &tpb.Consistency{},
Version: req.UsernameHashVersion,
})
metrics.IncrCounterWithLabels([]string{"search_requests", "username_hash"}, 1, []metrics.Label{{Name: "hasVersion", Value: fmt.Sprint(req.UsernameHashVersion != nil)}, grpcStatusLabel(responseErr)})
if responseErr != nil {
// A non-nil err should be returned except in the case where it's "not found".
@ -210,13 +221,16 @@ func (h *KtQueryHandler) phoneNumberSearch(req *pb.SearchRequest, tree *transpar
if err != nil {
return nil, err
}
// A non-nil responseErr should be returned except in the case where it's "not found" for a phone number lookup.
// This is to prevent short-circuiting and creating a timing difference between an account that doesn't exist
// with the given phone number, and one that does but is undiscoverable.
phoneNumberResponse, responseErr := tree.Search(&tpb.TreeSearchRequest{
SearchKey: append([]byte{util.NumberPrefix}, []byte(req.E164SearchRequest.GetE164())...),
Consistency: &tpb.Consistency{},
Version: req.E164Version,
})
metrics.IncrCounterWithLabels([]string{"search_requests", "e164"}, 1, []metrics.Label{{Name: "hasVersion", Value: fmt.Sprint(req.E164Version != nil)}, grpcStatusLabel(responseErr)})
var valueForComparison []byte
if responseErr != nil {

View File

@ -118,9 +118,9 @@ func TestSearch_AciNotFound(t *testing.T) {
AciIdentityKey: validAciIdentityKey1,
Consistency: &tpb.Consistency{},
}, tree)
if grpcError, ok := status.FromError(err); grpcError.Code() != codes.NotFound || !ok {
if grpcError, ok := status.FromError(err); grpcError.Code() != codes.PermissionDenied || !ok {
t.Fatalf("Expected %v, got %v",
codes.NotFound, err)
codes.PermissionDenied, err)
} else if resp != nil {
t.Fatalf("Expected no search response")
}

View File

@ -134,11 +134,14 @@ type SearchRequest struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Aci []byte `protobuf:"bytes,1,opt,name=aci,proto3" json:"aci,omitempty"`
AciIdentityKey []byte `protobuf:"bytes,2,opt,name=aci_identity_key,json=aciIdentityKey,proto3" json:"aci_identity_key,omitempty"`
UsernameHash []byte `protobuf:"bytes,3,opt,name=username_hash,json=usernameHash,proto3,oneof" json:"username_hash,omitempty"`
E164SearchRequest *E164SearchRequest `protobuf:"bytes,4,opt,name=e164_search_request,json=e164SearchRequest,proto3,oneof" json:"e164_search_request,omitempty"`
Consistency *pb.Consistency `protobuf:"bytes,5,opt,name=consistency,proto3" json:"consistency,omitempty"`
Aci []byte `protobuf:"bytes,1,opt,name=aci,proto3" json:"aci,omitempty"`
AciIdentityKey []byte `protobuf:"bytes,2,opt,name=aci_identity_key,json=aciIdentityKey,proto3" json:"aci_identity_key,omitempty"`
UsernameHash []byte `protobuf:"bytes,3,opt,name=username_hash,json=usernameHash,proto3,oneof" json:"username_hash,omitempty"`
E164SearchRequest *E164SearchRequest `protobuf:"bytes,4,opt,name=e164_search_request,json=e164SearchRequest,proto3,oneof" json:"e164_search_request,omitempty"`
Consistency *pb.Consistency `protobuf:"bytes,5,opt,name=consistency,proto3" json:"consistency,omitempty"`
AciVersion *uint32 `protobuf:"varint,6,opt,name=aci_version,json=aciVersion,proto3,oneof" json:"aci_version,omitempty"`
E164Version *uint32 `protobuf:"varint,7,opt,name=e164_version,json=e164Version,proto3,oneof" json:"e164_version,omitempty"`
UsernameHashVersion *uint32 `protobuf:"varint,8,opt,name=username_hash_version,json=usernameHashVersion,proto3,oneof" json:"username_hash_version,omitempty"`
}
func (x *SearchRequest) Reset() {
@ -206,6 +209,27 @@ func (x *SearchRequest) GetConsistency() *pb.Consistency {
return nil
}
func (x *SearchRequest) GetAciVersion() uint32 {
if x != nil && x.AciVersion != nil {
return *x.AciVersion
}
return 0
}
func (x *SearchRequest) GetE164Version() uint32 {
if x != nil && x.E164Version != nil {
return *x.E164Version
}
return 0
}
func (x *SearchRequest) GetUsernameHashVersion() uint32 {
if x != nil && x.UsernameHashVersion != nil {
return *x.UsernameHashVersion
}
return 0
}
// E164SearchRequest contains the data that the user must provide when looking up an E164
type E164SearchRequest struct {
state protoimpl.MessageState
@ -750,7 +774,7 @@ var file_key_transparency_query_proto_rawDesc = []byte{
0x32, 0x25, 0x2e, 0x6b, 0x74, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x64,
0x65, 0x6e, 0x73, 0x65, 0x64, 0x54, 0x72, 0x65, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0d, 0x64, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67,
0x75, 0x69, 0x73, 0x68, 0x65, 0x64, 0x22, 0xae, 0x02, 0x0a, 0x0d, 0x53, 0x65, 0x61, 0x72, 0x63,
0x75, 0x69, 0x73, 0x68, 0x65, 0x64, 0x22, 0xf0, 0x03, 0x0a, 0x0d, 0x53, 0x65, 0x61, 0x72, 0x63,
0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x69, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x61, 0x63, 0x69, 0x12, 0x28, 0x0a, 0x10, 0x61, 0x63,
0x69, 0x5f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02,
@ -766,130 +790,142 @@ var file_key_transparency_query_proto_rawDesc = []byte{
0x12, 0x3b, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18,
0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72,
0x65, 0x6e, 0x63, 0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79,
0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x42, 0x10, 0x0a,
0x0e, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x42,
0x16, 0x0a, 0x14, 0x5f, 0x65, 0x31, 0x36, 0x34, 0x5f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f,
0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x6d, 0x0a, 0x11, 0x45, 0x31, 0x36, 0x34, 0x53,
0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x04,
0x65, 0x31, 0x36, 0x34, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x65, 0x31,
0x36, 0x34, 0x88, 0x01, 0x01, 0x12, 0x36, 0x0a, 0x17, 0x75, 0x6e, 0x69, 0x64, 0x65, 0x6e, 0x74,
0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6b, 0x65, 0x79,
0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x15, 0x75, 0x6e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69,
0x66, 0x69, 0x65, 0x64, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x42, 0x07, 0x0a,
0x05, 0x5f, 0x65, 0x31, 0x36, 0x34, 0x22, 0xb8, 0x01, 0x0a, 0x1b, 0x43, 0x6f, 0x6e, 0x64, 0x65,
0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x24, 0x0a,
0x0b, 0x61, 0x63, 0x69, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01,
0x28, 0x0d, 0x48, 0x02, 0x52, 0x0a, 0x61, 0x63, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
0x88, 0x01, 0x01, 0x12, 0x26, 0x0a, 0x0c, 0x65, 0x31, 0x36, 0x34, 0x5f, 0x76, 0x65, 0x72, 0x73,
0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x03, 0x52, 0x0b, 0x65, 0x31, 0x36,
0x34, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x37, 0x0a, 0x15, 0x75,
0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x5f, 0x76, 0x65, 0x72,
0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x04, 0x52, 0x13, 0x75, 0x73,
0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x48, 0x61, 0x73, 0x68, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x6e, 0x88, 0x01, 0x01, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d,
0x65, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x42, 0x16, 0x0a, 0x14, 0x5f, 0x65, 0x31, 0x36, 0x34, 0x5f,
0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x42, 0x0e,
0x0a, 0x0c, 0x5f, 0x61, 0x63, 0x69, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x0f,
0x0a, 0x0d, 0x5f, 0x65, 0x31, 0x36, 0x34, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42,
0x18, 0x0a, 0x16, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x68, 0x61, 0x73,
0x68, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x6d, 0x0a, 0x11, 0x45, 0x31, 0x36,
0x34, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17,
0x0a, 0x04, 0x65, 0x31, 0x36, 0x34, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04,
0x65, 0x31, 0x36, 0x34, 0x88, 0x01, 0x01, 0x12, 0x36, 0x0a, 0x17, 0x75, 0x6e, 0x69, 0x64, 0x65,
0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6b,
0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x15, 0x75, 0x6e, 0x69, 0x64, 0x65, 0x6e,
0x74, 0x69, 0x66, 0x69, 0x65, 0x64, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4b, 0x65, 0x79, 0x42,
0x07, 0x0a, 0x05, 0x5f, 0x65, 0x31, 0x36, 0x34, 0x22, 0xb8, 0x01, 0x0a, 0x1b, 0x43, 0x6f, 0x6e,
0x64, 0x65, 0x6e, 0x73, 0x65, 0x64, 0x54, 0x72, 0x65, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x76, 0x72, 0x66, 0x5f,
0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x76, 0x72, 0x66,
0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x31, 0x0a, 0x06, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x18,
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72,
0x65, 0x6e, 0x63, 0x79, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x50, 0x72, 0x6f, 0x6f, 0x66,
0x52, 0x06, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x65, 0x6e,
0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6f, 0x70, 0x65, 0x6e, 0x69,
0x6e, 0x67, 0x12, 0x2f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x19, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79,
0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61,
0x6c, 0x75, 0x65, 0x22, 0xae, 0x02, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x09, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x68,
0x65, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x72, 0x61, 0x6e,
0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x46, 0x75, 0x6c, 0x6c, 0x54, 0x72, 0x65,
0x65, 0x48, 0x65, 0x61, 0x64, 0x52, 0x08, 0x74, 0x72, 0x65, 0x65, 0x48, 0x65, 0x61, 0x64, 0x12,
0x37, 0x0a, 0x03, 0x61, 0x63, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6b,
0x74, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x64, 0x65, 0x6e, 0x73, 0x65,
0x64, 0x54, 0x72, 0x65, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x52, 0x03, 0x61, 0x63, 0x69, 0x12, 0x3e, 0x0a, 0x04, 0x65, 0x31, 0x36, 0x34,
0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6b, 0x74, 0x5f, 0x71, 0x75, 0x65, 0x72,
0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x64, 0x54, 0x72, 0x65, 0x65, 0x53,
0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52,
0x04, 0x65, 0x31, 0x36, 0x34, 0x88, 0x01, 0x01, 0x12, 0x4f, 0x0a, 0x0d, 0x75, 0x73, 0x65, 0x72,
0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x25, 0x2e, 0x6b, 0x74, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x64, 0x65,
0x6e, 0x73, 0x65, 0x64, 0x54, 0x72, 0x65, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x76, 0x72, 0x66, 0x5f, 0x70, 0x72,
0x6f, 0x6f, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x76, 0x72, 0x66, 0x50, 0x72,
0x6f, 0x6f, 0x66, 0x12, 0x31, 0x0a, 0x06, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e,
0x63, 0x79, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x06,
0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x65, 0x6e, 0x69, 0x6e,
0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67,
0x12, 0x2f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x19, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x55,
0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
0x65, 0x22, 0xae, 0x02, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x09, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x68, 0x65, 0x61,
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70,
0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x46, 0x75, 0x6c, 0x6c, 0x54, 0x72, 0x65, 0x65, 0x48,
0x65, 0x61, 0x64, 0x52, 0x08, 0x74, 0x72, 0x65, 0x65, 0x48, 0x65, 0x61, 0x64, 0x12, 0x37, 0x0a,
0x03, 0x61, 0x63, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6b, 0x74, 0x5f,
0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x64, 0x54,
0x72, 0x65, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x52, 0x03, 0x61, 0x63, 0x69, 0x12, 0x3e, 0x0a, 0x04, 0x65, 0x31, 0x36, 0x34, 0x18, 0x03,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x6b, 0x74, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e,
0x43, 0x6f, 0x6e, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x64, 0x54, 0x72, 0x65, 0x65, 0x53, 0x65, 0x61,
0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x04, 0x65,
0x31, 0x36, 0x34, 0x88, 0x01, 0x01, 0x12, 0x4f, 0x0a, 0x0d, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61,
0x6d, 0x65, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e,
0x6b, 0x74, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x64, 0x65, 0x6e, 0x73,
0x65, 0x64, 0x54, 0x72, 0x65, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x48, 0x01, 0x52, 0x0c, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65,
0x48, 0x61, 0x73, 0x68, 0x88, 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x65, 0x31, 0x36, 0x34,
0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x68, 0x61,
0x73, 0x68, 0x22, 0x9e, 0x02, 0x0a, 0x0e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x03, 0x61, 0x63, 0x69, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6b, 0x74, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x41, 0x63,
0x69, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52,
0x03, 0x61, 0x63, 0x69, 0x12, 0x4e, 0x0a, 0x0d, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65,
0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6b, 0x74,
0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x48,
0x61, 0x73, 0x68, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x48, 0x00, 0x52, 0x0c, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x48, 0x61, 0x73,
0x68, 0x88, 0x01, 0x01, 0x12, 0x35, 0x0a, 0x04, 0x65, 0x31, 0x36, 0x34, 0x18, 0x03, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6b, 0x74, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x45, 0x31,
0x36, 0x34, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x48, 0x01, 0x52, 0x04, 0x65, 0x31, 0x36, 0x34, 0x88, 0x01, 0x01, 0x12, 0x3b, 0x0a, 0x0b, 0x63,
0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x19, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e,
0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x0b, 0x63, 0x6f, 0x6e,
0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x75, 0x73, 0x65,
0x72, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x65,
0x31, 0x36, 0x34, 0x22, 0x77, 0x0a, 0x11, 0x41, 0x63, 0x69, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f,
0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63, 0x69, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x61, 0x63, 0x69, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x6e,
0x74, 0x72, 0x79, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01,
0x28, 0x04, 0x52, 0x0d, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f,
0x6e, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x5f,
0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x63, 0x6f, 0x6d,
0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x93, 0x01, 0x0a,
0x1a, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x48, 0x61, 0x73, 0x68, 0x4d, 0x6f, 0x6e,
0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x75,
0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0c, 0x52, 0x0c, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x48, 0x61, 0x73, 0x68,
0x12, 0x25, 0x0a, 0x0e, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69,
0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x50,
0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x69,
0x74, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28,
0x0c, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x64,
0x65, 0x78, 0x22, 0x88, 0x01, 0x0a, 0x12, 0x45, 0x31, 0x36, 0x34, 0x4d, 0x6f, 0x6e, 0x69, 0x74,
0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x04, 0x65, 0x31, 0x36,
0x34, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x65, 0x31, 0x36, 0x34, 0x88,
0x01, 0x01, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x70, 0x6f, 0x73, 0x69,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x01, 0x52, 0x0c, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61,
0x6d, 0x65, 0x48, 0x61, 0x73, 0x68, 0x88, 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x65, 0x31,
0x36, 0x34, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x5f,
0x68, 0x61, 0x73, 0x68, 0x22, 0x9e, 0x02, 0x0a, 0x0e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x03, 0x61, 0x63, 0x69, 0x18, 0x01,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6b, 0x74, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e,
0x41, 0x63, 0x69, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x52, 0x03, 0x61, 0x63, 0x69, 0x12, 0x4e, 0x0a, 0x0d, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61,
0x6d, 0x65, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e,
0x6b, 0x74, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d,
0x65, 0x48, 0x61, 0x73, 0x68, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x48,
0x61, 0x73, 0x68, 0x88, 0x01, 0x01, 0x12, 0x35, 0x0a, 0x04, 0x65, 0x31, 0x36, 0x34, 0x18, 0x03,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6b, 0x74, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e,
0x45, 0x31, 0x36, 0x34, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x48, 0x01, 0x52, 0x04, 0x65, 0x31, 0x36, 0x34, 0x88, 0x01, 0x01, 0x12, 0x3b, 0x0a,
0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x04, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63,
0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x0b, 0x63,
0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x75,
0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x42, 0x07, 0x0a, 0x05,
0x5f, 0x65, 0x31, 0x36, 0x34, 0x22, 0x77, 0x0a, 0x11, 0x41, 0x63, 0x69, 0x4d, 0x6f, 0x6e, 0x69,
0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x63,
0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x61, 0x63, 0x69, 0x12, 0x25, 0x0a, 0x0e,
0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02,
0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x73, 0x69, 0x74,
0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e,
0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x63,
0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x93,
0x01, 0x0a, 0x1a, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x48, 0x61, 0x73, 0x68, 0x4d,
0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a,
0x0d, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01,
0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x48, 0x61,
0x73, 0x68, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x70, 0x6f, 0x73, 0x69,
0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x65, 0x6e, 0x74, 0x72,
0x79, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, 0x6d,
0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, 0x20,
0x01, 0x28, 0x0c, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x49,
0x6e, 0x64, 0x65, 0x78, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x65, 0x31, 0x36, 0x34, 0x22, 0xac, 0x02,
0x0a, 0x0f, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x37, 0x0a, 0x09, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x18, 0x01,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65,
0x6e, 0x63, 0x79, 0x2e, 0x46, 0x75, 0x6c, 0x6c, 0x54, 0x72, 0x65, 0x65, 0x48, 0x65, 0x61, 0x64,
0x52, 0x08, 0x74, 0x72, 0x65, 0x65, 0x48, 0x65, 0x61, 0x64, 0x12, 0x2c, 0x0a, 0x03, 0x61, 0x63,
0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70,
0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x72,
0x6f, 0x6f, 0x66, 0x52, 0x03, 0x61, 0x63, 0x69, 0x12, 0x44, 0x0a, 0x0d, 0x75, 0x73, 0x65, 0x72,
0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x1a, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x4d,
0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x48, 0x00, 0x52, 0x0c, 0x75,
0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x48, 0x61, 0x73, 0x68, 0x88, 0x01, 0x01, 0x12, 0x33,
0x0a, 0x04, 0x65, 0x31, 0x36, 0x34, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74,
0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x4d, 0x6f, 0x6e, 0x69,
0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x48, 0x01, 0x52, 0x04, 0x65, 0x31, 0x36, 0x34,
0x88, 0x01, 0x01, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e,
0x18, 0x05, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x09, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f,
0x6e, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x68,
0x61, 0x73, 0x68, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x65, 0x31, 0x36, 0x34, 0x32, 0xf2, 0x01, 0x0a,
0x1b, 0x4b, 0x65, 0x79, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79,
0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x52, 0x0a, 0x0d,
0x44, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x75, 0x69, 0x73, 0x68, 0x65, 0x64, 0x12, 0x1e, 0x2e,
0x6b, 0x74, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x44, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67,
0x75, 0x69, 0x73, 0x68, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e,
0x6b, 0x74, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x44, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67,
0x75, 0x69, 0x73, 0x68, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00,
0x12, 0x3d, 0x0a, 0x06, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x17, 0x2e, 0x6b, 0x74, 0x5f,
0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6b, 0x74, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x53,
0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12,
0x40, 0x0a, 0x07, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x12, 0x18, 0x2e, 0x6b, 0x74, 0x5f,
0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6b, 0x74, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e,
0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x00, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x61, 0x70, 0x70, 0x2f, 0x6b, 0x65, 0x79, 0x74, 0x72, 0x61,
0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x6b, 0x74,
0x2d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x33,
0x6e, 0x64, 0x65, 0x78, 0x22, 0x88, 0x01, 0x0a, 0x12, 0x45, 0x31, 0x36, 0x34, 0x4d, 0x6f, 0x6e,
0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x04, 0x65,
0x31, 0x36, 0x34, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x65, 0x31, 0x36,
0x34, 0x88, 0x01, 0x01, 0x12, 0x25, 0x0a, 0x0e, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x70, 0x6f,
0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x65, 0x6e,
0x74, 0x72, 0x79, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x63,
0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18,
0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e,
0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x65, 0x31, 0x36, 0x34, 0x22,
0xac, 0x02, 0x0a, 0x0f, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x09, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61,
0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x46, 0x75, 0x6c, 0x6c, 0x54, 0x72, 0x65, 0x65, 0x48, 0x65,
0x61, 0x64, 0x52, 0x08, 0x74, 0x72, 0x65, 0x65, 0x48, 0x65, 0x61, 0x64, 0x12, 0x2c, 0x0a, 0x03,
0x61, 0x63, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x72, 0x61, 0x6e,
0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72,
0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x03, 0x61, 0x63, 0x69, 0x12, 0x44, 0x0a, 0x0d, 0x75, 0x73,
0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79,
0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x48, 0x00, 0x52,
0x0c, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x48, 0x61, 0x73, 0x68, 0x88, 0x01, 0x01,
0x12, 0x33, 0x0a, 0x04, 0x65, 0x31, 0x36, 0x34, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x4d, 0x6f,
0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x48, 0x01, 0x52, 0x04, 0x65, 0x31,
0x36, 0x34, 0x88, 0x01, 0x01, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69,
0x6f, 0x6e, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x09, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x73,
0x69, 0x6f, 0x6e, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65,
0x5f, 0x68, 0x61, 0x73, 0x68, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x65, 0x31, 0x36, 0x34, 0x32, 0xf2,
0x01, 0x0a, 0x1b, 0x4b, 0x65, 0x79, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e,
0x63, 0x79, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x52,
0x0a, 0x0d, 0x44, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x75, 0x69, 0x73, 0x68, 0x65, 0x64, 0x12,
0x1e, 0x2e, 0x6b, 0x74, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x44, 0x69, 0x73, 0x74, 0x69,
0x6e, 0x67, 0x75, 0x69, 0x73, 0x68, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x1f, 0x2e, 0x6b, 0x74, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x44, 0x69, 0x73, 0x74, 0x69,
0x6e, 0x67, 0x75, 0x69, 0x73, 0x68, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0x00, 0x12, 0x3d, 0x0a, 0x06, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x17, 0x2e, 0x6b,
0x74, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6b, 0x74, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79,
0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x00, 0x12, 0x40, 0x0a, 0x07, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x12, 0x18, 0x2e, 0x6b,
0x74, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6b, 0x74, 0x5f, 0x71, 0x75, 0x65, 0x72,
0x79, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x22, 0x00, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
0x6d, 0x2f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x61, 0x70, 0x70, 0x2f, 0x6b, 0x65, 0x79, 0x74,
0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2f, 0x63, 0x6d, 0x64, 0x2f,
0x6b, 0x74, 0x2d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x33,
}
var (

View File

@ -48,6 +48,9 @@ message SearchRequest {
optional bytes username_hash = 3;
optional E164SearchRequest e164_search_request = 4;
transparency.Consistency consistency = 5;
optional uint32 aci_version = 6;
optional uint32 e164_version = 7;
optional uint32 username_hash_version = 8;
}
// E164SearchRequest contains the data that the user must provide when looking up an E164

View File

@ -34,7 +34,9 @@ api:
# fake:
# count: 1
# interval: 10s
distinguished: 1m
# This distinguished value is intentionally large for local development purposes: it's easier to adjust this value down
# and re-run the local server than to find that the tree accidentally grew too big and start the entire log over again.
distinguished: 1000h
auditors:
example-auditor-1: abcdef1234abcdef1234abcdef1234abcdef1234abcdef1234abcdef1234abcd
example-auditor-2: abcdef1234abcdef1234abcdef1234abcdef1234abcdef1234abcdef1234abcd

View File

@ -118,12 +118,12 @@ func TestLookupPattern(t *testing.T) {
// Insert a bunch of random keys.
var key []byte
for version := uint64(0); version < 300; version++ {
for treeSize := uint64(0); treeSize < 300; treeSize++ {
temp := random()
_, _, err := tree.Insert(version, temp, make([]byte, 32), false)
_, _, err := tree.Insert(treeSize, temp, make([]byte, 32), false)
if err != nil {
t.Fatal(err)
} else if version == 9 {
} else if treeSize == 9 {
key = temp
}
}
@ -131,7 +131,7 @@ func TestLookupPattern(t *testing.T) {
for i := 0; i < 100; i++ {
store.cache = make(map[uint64][]byte)
// Choose two random versions to do lookups in.
// Choose two random tree sizes to do lookups in.
ver1 := uint64(mrand.Intn(290) + 10)
ver2 := uint64(mrand.Intn(290) + 10)
if ver1 == ver2 {

View File

@ -25,10 +25,12 @@ import (
const IndexLength = 32
// SearchResult is the output from executing a search in a given version of the prefix tree for an index.
// SearchResult is the output from executing a search in a specific prefix tree for an index.
//
// There are two use cases for searching the prefix tree:
// 1. ["Indexing"] To find the log entry position of the most recent update to an index, along with the first update position.
// 1. ["Indexing"] To find the log entry positions of:
// 1. the first update, and
// 2. the most recent update OR the update corresponding to the desired version.
// This allows the server to conduct a more efficient binary search in the *log tree* for that log entry position.
// In this use case, the server will always start out searching the latest log entry and will only use FirstUpdatePosition and LatestUpdatePosition
// from the search result.
@ -40,14 +42,15 @@ type SearchResult struct {
// FirstUpdatePosition returns the log entry position of the first occurrence of this index in the given prefix tree.
FirstUpdatePosition uint64
// LatestUpdatePosition returns the log entry position of the most recent occurrence of the index in the given prefix tree.
// Note that the given prefix tree is not necessarily the one associated with latest log entry.
LatestUpdatePosition uint64
// Commitment returns the commitment associated with this version of the prefix
// tree. It may return nil if this version of the prefix tree was created by a fake update.
// Commitment returns the commitment associated with this prefix tree.
// It may return nil if this prefix tree was created by a fake update.
Commitment []byte
// Proof returns a proof of inclusion from the prefix tree leaf where the search terminated to the prefix tree root.
Proof [][]byte
// Counter returns how many times the index has been updated in the given version of the prefix tree.
// Counter returns how many times the index has been updated in this prefix tree.
Counter uint32
}
@ -66,13 +69,13 @@ func NewTree(aesKey []byte, tx db.PrefixStore) *Tree {
}
// BatchSearch returns an unexecuted search structure.
func (t *Tree) BatchSearch(version uint64, index []byte) (*Search, error) {
if version == 0 {
func (t *Tree) BatchSearch(treeSize uint64, index []byte) (*Search, error) {
if treeSize == 0 {
return nil, errors.New("tree is empty")
} else if len(index) != IndexLength {
return nil, fmt.Errorf("index length must be %v bytes", IndexLength)
}
return &Search{index: index, ptr: version - 1}, nil
return &Search{index: index, ptr: treeSize - 1}, nil
}
// BatchExec runs several searches in parallel, minimizing the number of
@ -100,9 +103,40 @@ func (t *Tree) BatchExec(searches []*Search) ([]*SearchResult, error) {
return out, nil
}
// Search executes a search for `index` in the requested version of the tree.
func (t *Tree) Search(version uint64, index []byte) (*SearchResult, error) {
search, err := t.BatchSearch(version, index)
// SearchForVersion executes a search in the tree of the given size for the index with a counter value
// equal to indexVersion.
// The SearchResult returns the latest update position *in the last tree size that was searched*, which is not necessarily
// the original treeSize.
func (t *Tree) SearchForVersion(treeSize uint64, index []byte, indexVersion uint32) (*SearchResult, error) {
var res *SearchResult
nextTreeSizeToSearch := treeSize
// Search for the index with the requested indexVersion counter by recursively searching in earlier
// and earlier entries of the log for the most recent update to the given index, until we find the desired index version
// or we get back a "not found" error.
var err error
for {
res, err = t.Search(nextTreeSizeToSearch, index)
if err != nil {
return nil, fmt.Errorf("running versioned search: %w", err)
}
if res.Counter != indexVersion {
// Tree size is one-indexed, but positions are zero-indexed. For example,
// if index A's latest update position is 8, that means that that update was the 9th entry in the tree.
// So in the next iteration, we want to search in the tree with 8 entries for the latest update to index A.
nextTreeSizeToSearch = res.LatestUpdatePosition
} else {
break
}
}
return res, nil
}
// Search executes a search for `index` in the requested tree.
func (t *Tree) Search(treeSize uint64, index []byte) (*SearchResult, error) {
search, err := t.BatchSearch(treeSize, index)
if err != nil {
return nil, fmt.Errorf("creating search: %w", err)
}
@ -116,8 +150,8 @@ func (t *Tree) Search(version uint64, index []byte) (*SearchResult, error) {
// Trace performs the same database lookups in the same order as Search, without
// computing the intermediate hashes to produce a full search result. This is
// used for populating caches.
func (t *Tree) Trace(version uint64, index []byte) error {
search, err := t.BatchSearch(version, index)
func (t *Tree) Trace(treeSize uint64, index []byte) error {
search, err := t.BatchSearch(treeSize, index)
if err != nil {
return fmt.Errorf("creating search: %w", err)
}
@ -131,15 +165,15 @@ func (t *Tree) Trace(version uint64, index []byte) error {
// InsertFake changes the tree like a random new entry was inserted, without
// actually doing so.
//
// The current tree version is given in `version`; after this method returns
// successfully, the tree may be used with `version+1`.
func (t *Tree) InsertFake(version uint64) ([]byte, error) {
// The current tree size is given in `treeSize`; after this method returns
// successfully, the tree may be used with `treeSize+1`.
func (t *Tree) InsertFake(treeSize uint64) ([]byte, error) {
var entry *pb.LogEntry
if version == 0 {
if treeSize == 0 {
// entry = &pb.LogEntry{
// Index: nil,
// Copath: nil,
// Seed: version,
// Seed: treeSize,
// }
return nil, fmt.Errorf("can not do fake insert in an empty tree")
} else {
@ -147,7 +181,7 @@ func (t *Tree) InsertFake(version uint64) ([]byte, error) {
if _, err := rand.Read(index); err != nil {
return nil, fmt.Errorf("getting randomness: %w", err)
}
search, err := t.BatchSearch(version, index)
search, err := t.BatchSearch(treeSize, index)
if err != nil {
return nil, fmt.Errorf("creating search: %w", err)
}
@ -163,7 +197,7 @@ func (t *Tree) InsertFake(version uint64) ([]byte, error) {
entry = &pb.LogEntry{
Index: index[:cutoff],
Copath: failed.copath,
FirstUpdatePosition: version,
FirstUpdatePosition: treeSize,
}
}
@ -174,7 +208,7 @@ func (t *Tree) InsertFake(version uint64) ([]byte, error) {
if err != nil {
return nil, err
}
t.tx.Put(version, raw)
t.tx.Put(treeSize, raw)
return cached.rollup(0), nil
}
@ -185,9 +219,9 @@ type Entry struct {
// sequence is a wrapper around sequencePart, that allows sequencing to happen
// on many cores instead of just one.
func (t *Tree) sequence(version uint64, entries []Entry, fake bool) ([]*cachedLogEntry, error) {
func (t *Tree) sequence(treeSize uint64, entries []Entry, fake bool) ([]*cachedLogEntry, error) {
if len(entries) < 64 { // Skip multi-threaded stuff for small batches.
return t.sequencePart(version, 0, entries, fake)
return t.sequencePart(treeSize, 0, entries, fake)
}
type sequenceResult struct {
@ -212,7 +246,7 @@ func (t *Tree) sequence(version uint64, entries []Entry, fake bool) ([]*cachedLo
j = len(entries)
}
go func() {
part, err := t.sequencePart(version, i, entries[i:j], fake)
part, err := t.sequencePart(treeSize, i, entries[i:j], fake)
ch <- sequenceResult{i, part, err}
}()
goroutines++
@ -233,12 +267,12 @@ func (t *Tree) sequence(version uint64, entries []Entry, fake bool) ([]*cachedLo
// sequencePart takes a subset of new entries to insert into the prefix tree and
// returns a cachedLogEntry for each, corresponding to the log entry that would
// be stored if it were version+1 of the tree.
// be stored if the tree had treeSize+1 entries.
// fake is whether the provided log entries are fake, which affects the data stored in the cachedLogEntry.
func (t *Tree) sequencePart(version uint64, offset int, entries []Entry, fake bool) ([]*cachedLogEntry, error) {
func (t *Tree) sequencePart(treeSize uint64, offset int, entries []Entry, fake bool) ([]*cachedLogEntry, error) {
var searches []*Search
for _, entry := range entries {
search, err := t.BatchSearch(version, entry.Index)
search, err := t.BatchSearch(treeSize, entry.Index)
if err != nil {
return nil, fmt.Errorf("creating search: %w", err)
}
@ -261,7 +295,7 @@ func (t *Tree) sequencePart(version uint64, offset int, entries []Entry, fake bo
temp := &cachedLogEntry{
inner: &pb.LogEntry{
Copath: res.copath,
FirstUpdatePosition: version + uint64(offset+i),
FirstUpdatePosition: treeSize + uint64(offset+i),
},
aesKey: t.aesKey,
}
@ -295,9 +329,9 @@ func (t *Tree) sequencePart(version uint64, offset int, entries []Entry, fake bo
// of entries that already exist. It returns the new roots and a search result
// for each entry.
//
// The current tree version is given in `version`; after this method returns
// successfully, the tree may be used with `version+len(entries)`.
func (t *Tree) BatchInsert(version uint64, entries []Entry, fake bool) ([][]byte, []*SearchResult, error) {
// The current treeSize is given in `treeSize`; after this method returns
// successfully, the tree may be used with `treeSize+len(entries)`.
func (t *Tree) BatchInsert(treeSize uint64, entries []Entry, fake bool) ([][]byte, []*SearchResult, error) {
if len(entries) == 0 {
return nil, nil, errors.New("no entries to insert provided")
}
@ -310,7 +344,7 @@ func (t *Tree) BatchInsert(version uint64, entries []Entry, fake bool) ([][]byte
}
var sequenced []*cachedLogEntry
if version == 0 {
if treeSize == 0 {
// Do not insert fake entries into an empty tree
if fake {
return nil, nil, errors.New("cannot insert fake entries into an empty tree")
@ -320,7 +354,7 @@ func (t *Tree) BatchInsert(version uint64, entries []Entry, fake bool) ([][]byte
inner: &pb.LogEntry{
Index: entry.Index,
Copath: nil,
FirstUpdatePosition: version + uint64(i),
FirstUpdatePosition: treeSize + uint64(i),
Leaf: &pb.LeafNode{Ctr: 0, Commitment: entry.Commitment},
},
aesKey: t.aesKey,
@ -328,16 +362,16 @@ func (t *Tree) BatchInsert(version uint64, entries []Entry, fake bool) ([][]byte
}
} else {
var err error
sequenced, err = t.sequence(version, entries, fake)
sequenced, err = t.sequence(treeSize, entries, fake)
if err != nil {
return nil, nil, err
}
}
// All the entries in the `sequenced` slice are constructed as if they're
// going to be version+1 of the tree. Update them so that they're in order.
// going to be treeSize+1 of the tree. Update them so that they're in order.
for i := 1; i < len(sequenced); i++ {
search := &Search{index: sequenced[i].inner.Index, ptr: version - 1 + uint64(i)}
search := &Search{index: sequenced[i].inner.Index, ptr: treeSize - 1 + uint64(i)}
ptr := i - 1
for {
// Search the prefix tree of the log entry associated with `ptr`.
@ -347,8 +381,8 @@ func (t *Tree) BatchInsert(version uint64, entries []Entry, fake bool) ([][]byte
case uint64:
// If the next step of the search jumps to a previous entry in the sequencing batch,
// we can grab that log entry from the `sequenced` slice and continue our search
if res >= version {
ptr = int(res - version)
if res >= treeSize {
ptr = int(res - treeSize)
continue
}
// Otherwise, the search jumped to a log entry less than the starting log tree size before the batch update.
@ -396,7 +430,7 @@ func (t *Tree) BatchInsert(version uint64, entries []Entry, fake bool) ([][]byte
if err != nil {
return nil, nil, err
}
t.tx.Put(version+uint64(i), raw)
t.tx.Put(treeSize+uint64(i), raw)
roots = append(roots, entry.rollup(0))
@ -407,7 +441,7 @@ func (t *Tree) BatchInsert(version uint64, entries []Entry, fake bool) ([][]byte
Counter: entry.inner.Leaf.Ctr,
FirstUpdatePosition: entry.inner.FirstUpdatePosition,
LatestUpdatePosition: version + uint64(i),
LatestUpdatePosition: treeSize + uint64(i),
Commitment: entry.inner.Leaf.Commitment,
})
}
@ -417,15 +451,15 @@ func (t *Tree) BatchInsert(version uint64, entries []Entry, fake bool) ([][]byte
// Insert adds a new index to the tree or increments its counter if it already
// exists, and returns the new root and search result.
func (t *Tree) Insert(version uint64, index, commitment []byte, fake bool) ([]byte, *SearchResult, error) {
roots, srs, err := t.BatchInsert(version, []Entry{{index, commitment}}, fake)
func (t *Tree) Insert(treeSize uint64, index, commitment []byte, fake bool) ([]byte, *SearchResult, error) {
roots, srs, err := t.BatchInsert(treeSize, []Entry{{index, commitment}}, fake)
if err != nil {
return nil, nil, err
}
return roots[0], srs[0], nil
}
// LogEntries returns the stored log entries for the requested version range.
// LogEntries returns the stored log entries for the requested range.
func (t *Tree) LogEntries(start, end uint64) ([]*pb.LogEntry, [][]byte, [][]byte, error) {
var ids []uint64
for i := start; i < end; i++ {

View File

@ -23,6 +23,58 @@ func random() []byte {
return out
}
func TestPrefixTreeSearchForVersion(t *testing.T) {
var (
tree = NewTree(make([]byte, 16), db.NewMemoryTransparencyStore().PrefixStore())
repeatKey = random()
// The i-th value is the update position for version i of repeatKey
versionPositions []uint64
randomKeys [][]byte
treeSize uint64
)
for i := 0; i < 1000; i++ {
dice := mrand.Intn(4)
if dice == 0 && len(versionPositions) > 0 { // Search for a random version of the key
version := uint32(mrand.Intn(len(versionPositions)))
res, err := tree.SearchForVersion(treeSize, repeatKey, version)
if err != nil {
t.Fatal(err)
} else if res.Counter != version {
t.Fatal("unexpected value for version counter")
} else if res.FirstUpdatePosition != versionPositions[0] {
t.Fatal("unexpected value for first update position")
} else if res.LatestUpdatePosition != versionPositions[version] {
t.Fatal("unexpected value for version update position")
}
} else if dice == 1 && (len(randomKeys) > 0 || len(versionPositions) > 0) { // Insert a fake entry.
_, err := tree.InsertFake(treeSize)
if err != nil {
t.Fatal(err)
}
treeSize = treeSize + 1
} else if dice == 2 { // Insert a new index.
randomKey := random()
_, _, err := tree.Insert(treeSize, randomKey, make([]byte, 32), false)
if err != nil {
t.Fatal(err)
}
randomKeys = append(randomKeys, randomKey)
treeSize = treeSize + 1
} else if dice == 3 { // Insert repeatKey again
_, _, err := tree.Insert(treeSize, repeatKey, make([]byte, 32), false)
if err != nil {
t.Fatal(err)
}
versionPositions = append(versionPositions, treeSize)
treeSize = treeSize + 1
}
}
}
func TestPrefixTree(t *testing.T) {
var (
tree = NewTree(make([]byte, 16), db.NewMemoryTransparencyStore().PrefixStore())
@ -32,8 +84,8 @@ func TestPrefixTree(t *testing.T) {
firstUpdatePosition []uint64
latestUpdatePosition []uint64
version uint64
root []byte
treeSize uint64
root []byte
)
for i := 0; i < 1000; i++ {
@ -42,7 +94,7 @@ func TestPrefixTree(t *testing.T) {
if dice == 0 && len(keys) > 0 { // Search for an existing index.
k := mrand.Intn(len(keys))
res, err := tree.Search(version, keys[k])
res, err := tree.Search(treeSize, keys[k])
if err != nil {
t.Fatal(err)
} else if err = Verify(root, keys[k], firstUpdatePosition[k], res); err != nil {
@ -55,62 +107,62 @@ func TestPrefixTree(t *testing.T) {
t.Fatal("unexpected value for latest update position")
}
} else if dice == 1 && len(keys) > 0 { // Insert a fake entry.
temp, err := tree.InsertFake(version)
temp, err := tree.InsertFake(treeSize)
if err != nil {
t.Fatal(err)
}
version, root = version+1, temp
treeSize, root = treeSize+1, temp
} else if dice == 2 { // Insert a new index.
key := random()
temp, _, err := tree.Insert(version, key, make([]byte, 32), false)
temp, _, err := tree.Insert(treeSize, key, make([]byte, 32), false)
if err != nil {
t.Fatal(err)
}
keys = append(keys, key)
ctr = append(ctr, 0)
firstUpdatePosition = append(firstUpdatePosition, version)
latestUpdatePosition = append(latestUpdatePosition, version)
version, root = version+1, temp
firstUpdatePosition = append(firstUpdatePosition, treeSize)
latestUpdatePosition = append(latestUpdatePosition, treeSize)
treeSize, root = treeSize+1, temp
} else if dice == 3 && len(keys) > 0 { // Insert an existing index.
k := mrand.Intn(len(keys))
temp, _, err := tree.Insert(version, keys[k], make([]byte, 32), false)
temp, _, err := tree.Insert(treeSize, keys[k], make([]byte, 32), false)
if err != nil {
t.Fatal(err)
}
ctr[k] += 1
latestUpdatePosition[k] = version
version, root = version+1, temp
latestUpdatePosition[k] = treeSize
treeSize, root = treeSize+1, temp
}
}
}
func TestBatchSearch(t *testing.T) {
var (
tree = NewTree(make([]byte, 16), db.NewMemoryTransparencyStore().PrefixStore())
versions = []uint64{20, 50, 100, 200, 250}
tree = NewTree(make([]byte, 16), db.NewMemoryTransparencyStore().PrefixStore())
treeSizes = []uint64{20, 50, 100, 200, 250}
key []byte
roots [][]byte
commitments [][]byte
)
for version := uint64(0); version < 300; version++ {
for treeSize := uint64(0); treeSize < 300; treeSize++ {
temp := random()
root, sr, err := tree.Insert(version, temp, make([]byte, 32), false)
root, sr, err := tree.Insert(treeSize, temp, make([]byte, 32), false)
if err != nil {
t.Fatal(err)
}
if version == 10 {
if treeSize == 10 {
key = temp
} else if slices.Contains(versions, version+1) {
} else if slices.Contains(treeSizes, treeSize+1) {
roots = append(roots, root)
commitments = append(commitments, sr.Commitment)
}
}
searches := make([]*Search, 0)
for _, version := range versions {
search, err := tree.BatchSearch(version, key)
for _, treeSize := range treeSizes {
search, err := tree.BatchSearch(treeSize, key)
if err != nil {
t.Fatal(err)
}
@ -126,7 +178,7 @@ func TestBatchSearch(t *testing.T) {
} else if res.FirstUpdatePosition != 10 {
t.Fatal("unexpected value for first update position")
} else if res.LatestUpdatePosition != 10 {
t.Fatal("unexpected value for version position")
t.Fatal("unexpected value for latest update position")
} else if !bytes.Equal(res.Commitment, commitments[i]) {
t.Fatal("unexpected value for commitment")
}

View File

@ -24,10 +24,21 @@ func (s idCtrSlice) Len() int { return len(s) }
func (s idCtrSlice) Less(i, j int) bool { return s[i].id < s[j].id }
func (s idCtrSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
// proofGuide contains the data necessary to carry out a search of the implicit binary tree
// for a given index.
// The implicit binary tree is formed by arranging the log entries into a left-balanced binary search formation,
// proofGuide contains the data necessary to determine the search path through the implicit binary tree
// for the target log entry. It is used in two ways: for search proof generation and search proof verification.
//
// For context, the implicit binary tree is formed by arranging the log entries into a left-balanced binary search formation,
// where each node contains an entry ID and a counter value that denotes which "version" of a given index exists in that entry.
// While an index can have versions greater than 1, for the purposes of generating a search proof, we only use two counter values:
//
// 0: Denotes that this entry occurred before the target log entry
// 1: Denotes that this entry is either the target log entry or occurred after it
//
// Unlike search proof generation, during search proof verification, we don't know the target log entry position.
// Instead, we have the supposed steps of the search path (as generated by the key transparency server),
// along with the version of the index at each step. We use the provided version(s) to determine how to
// traverse the implicit binary search tree as part of the verification process.
//
// Unlike a typical binary search that would move left or right based on the entry ID alone, this search moves left and right
// based on two criteria:
// 1. The ctr value for each entry ID in the tree which is stored in the sorted field alongside the entry ID.
@ -61,6 +72,18 @@ func mostRecentProofGuide(firstUpdatePosition, treeSize uint64) *proofGuide {
return &proofGuide{firstUpdatePosition: firstUpdatePosition, treeSize: treeSize, ids: frontier, frontier: true}
}
// versionProofGuide initializes the data structure used to search for a specific version of an index.
// Unlike mostRecentProofGuide, it does not need to search the frontier nodes to determine targetCtr, and so it
// begins its search with only the root node.
func versionProofGuide(targetCtr uint32, firstUpdatePosition, treeSize uint64) *proofGuide {
return &proofGuide{
firstUpdatePosition: firstUpdatePosition,
treeSize: treeSize,
targetCtr: targetCtr,
ids: []uint64{math.Root(firstUpdatePosition, treeSize)},
}
}
// done returns true if the search proof is finished.
// Otherwise, it looks up and stores the next entry ID to search.
func (pg *proofGuide) done() (bool, error) {

View File

@ -6,6 +6,7 @@
package transparency
import (
"slices"
"testing"
)
@ -70,3 +71,17 @@ func TestMostRecentProofGuide(t *testing.T) {
t.Fatal("wrong result returned")
}
}
func TestVersionProofGuide(t *testing.T) {
guide := versionProofGuide(1, 1, 28)
ids := executeGuide(guide, 1, 28, 17)
if !slices.Equal([]uint64{15, 23, 19, 17, 16}, ids) {
t.Fatal("wrong result returned")
}
guide = versionProofGuide(1, 1, 28)
ids = executeGuide(guide, 1, 28, 27)
if !slices.Equal([]uint64{15, 23, 27, 25, 26}, ids) {
t.Fatal("wrong result returned")
}
}

View File

@ -625,6 +625,7 @@ type TreeSearchRequest struct {
SearchKey []byte `protobuf:"bytes,1,opt,name=search_key,json=searchKey,proto3" json:"search_key,omitempty"`
Consistency *Consistency `protobuf:"bytes,2,opt,name=consistency,proto3" json:"consistency,omitempty"`
Version *uint32 `protobuf:"varint,3,opt,name=version,proto3,oneof" json:"version,omitempty"`
}
func (x *TreeSearchRequest) Reset() {
@ -671,6 +672,13 @@ func (x *TreeSearchRequest) GetConsistency() *Consistency {
return nil
}
func (x *TreeSearchRequest) GetVersion() uint32 {
if x != nil && x.Version != nil {
return *x.Version
}
return 0
}
// TreeSearchResponse is the output of executing a search on the tree.
type TreeSearchResponse struct {
state protoimpl.MessageState
@ -1531,45 +1539,18 @@ var file_pb_transparency_proto_rawDesc = []byte{
0x67, 0x75, 0x69, 0x73, 0x68, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x48, 0x01, 0x52,
0x0d, 0x64, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x75, 0x69, 0x73, 0x68, 0x65, 0x64, 0x88, 0x01,
0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x64,
0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x75, 0x69, 0x73, 0x68, 0x65, 0x64, 0x22, 0x6f, 0x0a, 0x11,
0x54, 0x72, 0x65, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x6b, 0x65, 0x79, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x4b, 0x65, 0x79,
0x12, 0x3b, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18,
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72,
0x65, 0x6e, 0x63, 0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79,
0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x22, 0xe8, 0x01,
0x0a, 0x12, 0x54, 0x72, 0x65, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x09, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x68, 0x65, 0x61,
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70,
0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x46, 0x75, 0x6c, 0x6c, 0x54, 0x72, 0x65, 0x65, 0x48,
0x65, 0x61, 0x64, 0x52, 0x08, 0x74, 0x72, 0x65, 0x65, 0x48, 0x65, 0x61, 0x64, 0x12, 0x1b, 0x0a,
0x09, 0x76, 0x72, 0x66, 0x5f, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c,
0x52, 0x08, 0x76, 0x72, 0x66, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x31, 0x0a, 0x06, 0x73, 0x65,
0x61, 0x72, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x72, 0x61,
0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68,
0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x06, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x18, 0x0a,
0x07, 0x6f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07,
0x6f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x2f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61,
0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75,
0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xf2, 0x01, 0x0a, 0x0d, 0x55, 0x70, 0x64,
0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65,
0x61, 0x72, 0x63, 0x68, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09,
0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x4b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c,
0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12,
0x3b, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x03,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65,
0x6e, 0x63, 0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x52,
0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x39, 0x0a, 0x19,
0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x70, 0x72, 0x65, 0x5f, 0x75, 0x70, 0x64,
0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52,
0x16, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x72, 0x65, 0x55, 0x70, 0x64, 0x61,
0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x34, 0x0a, 0x16, 0x72, 0x65, 0x74, 0x75, 0x72,
0x6e, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x55,
0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xb3, 0x01,
0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x75, 0x69, 0x73, 0x68, 0x65, 0x64, 0x22, 0x9a, 0x01, 0x0a,
0x11, 0x54, 0x72, 0x65, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x6b, 0x65, 0x79,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x4b, 0x65,
0x79, 0x12, 0x3b, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79,
0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61,
0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63,
0x79, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x1d,
0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x48,
0x00, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x0a, 0x0a,
0x08, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xe8, 0x01, 0x0a, 0x12, 0x54, 0x72,
0x65, 0x65, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x12, 0x37, 0x0a, 0x09, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e,
0x63, 0x79, 0x2e, 0x46, 0x75, 0x6c, 0x6c, 0x54, 0x72, 0x65, 0x65, 0x48, 0x65, 0x61, 0x64, 0x52,
@ -1580,76 +1561,106 @@ var file_pb_transparency_proto_rawDesc = []byte{
0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x50, 0x72, 0x6f, 0x6f,
0x66, 0x52, 0x06, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x65,
0x6e, 0x69, 0x6e, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6f, 0x70, 0x65, 0x6e,
0x69, 0x6e, 0x67, 0x22, 0x7d, 0x0a, 0x0a, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x4b, 0x65,
0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x6b, 0x65, 0x79, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x4b, 0x65, 0x79,
0x12, 0x25, 0x0a, 0x0e, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69,
0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x50,
0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x69,
0x74, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28,
0x0c, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x64,
0x65, 0x78, 0x22, 0x7b, 0x0a, 0x0e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x18, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63,
0x79, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x4b, 0x65, 0x79, 0x52, 0x04, 0x6b, 0x65,
0x79, 0x73, 0x12, 0x3b, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63,
0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70,
0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e,
0x63, 0x79, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x22,
0x3d, 0x0a, 0x0c, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12,
0x2d, 0x0a, 0x05, 0x73, 0x74, 0x65, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17,
0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x50, 0x72,
0x6f, 0x6f, 0x66, 0x53, 0x74, 0x65, 0x70, 0x52, 0x05, 0x73, 0x74, 0x65, 0x70, 0x73, 0x22, 0x9c,
0x01, 0x0a, 0x0f, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x37, 0x0a, 0x09, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72,
0x65, 0x6e, 0x63, 0x79, 0x2e, 0x46, 0x75, 0x6c, 0x6c, 0x54, 0x72, 0x65, 0x65, 0x48, 0x65, 0x61,
0x64, 0x52, 0x08, 0x74, 0x72, 0x65, 0x65, 0x48, 0x65, 0x61, 0x64, 0x12, 0x32, 0x0a, 0x06, 0x70,
0x72, 0x6f, 0x6f, 0x66, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x72,
0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74,
0x6f, 0x72, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x06, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x12,
0x1c, 0x0a, 0x09, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x03,
0x28, 0x0c, 0x52, 0x09, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x90, 0x03,
0x0a, 0x0c, 0x41, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x3f,
0x0a, 0x08, 0x6e, 0x65, 0x77, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x22, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e,
0x41, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x2e, 0x4e, 0x65, 0x77,
0x54, 0x72, 0x65, 0x65, 0x48, 0x00, 0x52, 0x07, 0x6e, 0x65, 0x77, 0x54, 0x72, 0x65, 0x65, 0x12,
0x4e, 0x0a, 0x0d, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x6b, 0x65, 0x79,
0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61,
0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f,
0x6f, 0x66, 0x2e, 0x44, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x48,
0x00, 0x52, 0x0c, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x12,
0x3f, 0x0a, 0x08, 0x73, 0x61, 0x6d, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x22, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79,
0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x2e, 0x53, 0x61,
0x6d, 0x65, 0x4b, 0x65, 0x79, 0x48, 0x00, 0x52, 0x07, 0x73, 0x61, 0x6d, 0x65, 0x4b, 0x65, 0x79,
0x1a, 0x09, 0x0a, 0x07, 0x4e, 0x65, 0x77, 0x54, 0x72, 0x65, 0x65, 0x1a, 0x41, 0x0a, 0x0c, 0x44,
0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x63,
0x6f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x06, 0x63, 0x6f, 0x70,
0x61, 0x74, 0x68, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x6c, 0x64, 0x5f, 0x73, 0x65, 0x65, 0x64, 0x18,
0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6f, 0x6c, 0x64, 0x53, 0x65, 0x65, 0x64, 0x1a, 0x57,
0x0a, 0x07, 0x53, 0x61, 0x6d, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x70,
0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x06, 0x63, 0x6f, 0x70, 0x61, 0x74,
0x68, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01,
0x28, 0x0d, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x70,
0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x70,
0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x07, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66,
0x22, 0x9f, 0x01, 0x0a, 0x0d, 0x41, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x55, 0x70, 0x64, 0x61,
0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x65, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08,
0x52, 0x04, 0x72, 0x65, 0x61, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18,
0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x12, 0x0a, 0x04,
0x73, 0x65, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x73, 0x65, 0x65, 0x64,
0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x04,
0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74,
0x12, 0x30, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x1a, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x41,
0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x05, 0x70, 0x72, 0x6f,
0x6f, 0x66, 0x42, 0x3b, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
0x2f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x61, 0x70, 0x70, 0x2f, 0x6b, 0x65, 0x79, 0x74, 0x72,
0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2f, 0x74, 0x72, 0x65, 0x65, 0x2f,
0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2f, 0x70, 0x62, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x69, 0x6e, 0x67, 0x12, 0x2f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63,
0x79, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76,
0x61, 0x6c, 0x75, 0x65, 0x22, 0xf2, 0x01, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68,
0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x65, 0x61, 0x72,
0x63, 0x68, 0x4b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02,
0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x63,
0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x19, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e,
0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x0b, 0x63, 0x6f, 0x6e,
0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x39, 0x0a, 0x19, 0x65, 0x78, 0x70, 0x65,
0x63, 0x74, 0x65, 0x64, 0x5f, 0x70, 0x72, 0x65, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f,
0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x16, 0x65, 0x78, 0x70,
0x65, 0x63, 0x74, 0x65, 0x64, 0x50, 0x72, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x61,
0x6c, 0x75, 0x65, 0x12, 0x34, 0x0a, 0x16, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x5f, 0x75, 0x70,
0x64, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x05, 0x20,
0x01, 0x28, 0x08, 0x52, 0x14, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x55, 0x70, 0x64, 0x61, 0x74,
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xb3, 0x01, 0x0a, 0x0e, 0x55, 0x70,
0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x09,
0x74, 0x72, 0x65, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x1a, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x46,
0x75, 0x6c, 0x6c, 0x54, 0x72, 0x65, 0x65, 0x48, 0x65, 0x61, 0x64, 0x52, 0x08, 0x74, 0x72, 0x65,
0x65, 0x48, 0x65, 0x61, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x76, 0x72, 0x66, 0x5f, 0x70, 0x72, 0x6f,
0x6f, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x76, 0x72, 0x66, 0x50, 0x72, 0x6f,
0x6f, 0x66, 0x12, 0x31, 0x0a, 0x06, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63,
0x79, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x06, 0x73,
0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67,
0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x22,
0x7d, 0x0a, 0x0a, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x4b, 0x65, 0x79, 0x12, 0x1d, 0x0a,
0x0a, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0c, 0x52, 0x09, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x4b, 0x65, 0x79, 0x12, 0x25, 0x0a, 0x0e,
0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02,
0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x50, 0x6f, 0x73, 0x69, 0x74,
0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e,
0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x63,
0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x7b,
0x0a, 0x0e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x12, 0x2c, 0x0a, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18,
0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x4d, 0x6f,
0x6e, 0x69, 0x74, 0x6f, 0x72, 0x4b, 0x65, 0x79, 0x52, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x12, 0x3b,
0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e,
0x63, 0x79, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x0b,
0x63, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x3d, 0x0a, 0x0c, 0x4d,
0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x2d, 0x0a, 0x05, 0x73,
0x74, 0x65, 0x70, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x72, 0x61,
0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x53,
0x74, 0x65, 0x70, 0x52, 0x05, 0x73, 0x74, 0x65, 0x70, 0x73, 0x22, 0x9c, 0x01, 0x0a, 0x0f, 0x4d,
0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37,
0x0a, 0x09, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79,
0x2e, 0x46, 0x75, 0x6c, 0x6c, 0x54, 0x72, 0x65, 0x65, 0x48, 0x65, 0x61, 0x64, 0x52, 0x08, 0x74,
0x72, 0x65, 0x65, 0x48, 0x65, 0x61, 0x64, 0x12, 0x32, 0x0a, 0x06, 0x70, 0x72, 0x6f, 0x6f, 0x66,
0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70,
0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x72,
0x6f, 0x6f, 0x66, 0x52, 0x06, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x69,
0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x09,
0x69, 0x6e, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x90, 0x03, 0x0a, 0x0c, 0x41, 0x75,
0x64, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x12, 0x3f, 0x0a, 0x08, 0x6e, 0x65,
0x77, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74,
0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x41, 0x75, 0x64, 0x69,
0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x2e, 0x4e, 0x65, 0x77, 0x54, 0x72, 0x65, 0x65,
0x48, 0x00, 0x52, 0x07, 0x6e, 0x65, 0x77, 0x54, 0x72, 0x65, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x64,
0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63,
0x79, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x2e, 0x44,
0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x48, 0x00, 0x52, 0x0c, 0x64,
0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x3f, 0x0a, 0x08, 0x73,
0x61, 0x6d, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e,
0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x41, 0x75, 0x64,
0x69, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x2e, 0x53, 0x61, 0x6d, 0x65, 0x4b, 0x65,
0x79, 0x48, 0x00, 0x52, 0x07, 0x73, 0x61, 0x6d, 0x65, 0x4b, 0x65, 0x79, 0x1a, 0x09, 0x0a, 0x07,
0x4e, 0x65, 0x77, 0x54, 0x72, 0x65, 0x65, 0x1a, 0x41, 0x0a, 0x0c, 0x44, 0x69, 0x66, 0x66, 0x65,
0x72, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x70, 0x61, 0x74,
0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x06, 0x63, 0x6f, 0x70, 0x61, 0x74, 0x68, 0x12,
0x19, 0x0a, 0x08, 0x6f, 0x6c, 0x64, 0x5f, 0x73, 0x65, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
0x0c, 0x52, 0x07, 0x6f, 0x6c, 0x64, 0x53, 0x65, 0x65, 0x64, 0x1a, 0x57, 0x0a, 0x07, 0x53, 0x61,
0x6d, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x70, 0x61, 0x74, 0x68, 0x18,
0x01, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x06, 0x63, 0x6f, 0x70, 0x61, 0x74, 0x68, 0x12, 0x18, 0x0a,
0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07,
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6f, 0x73, 0x69, 0x74,
0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x70, 0x6f, 0x73, 0x69, 0x74,
0x69, 0x6f, 0x6e, 0x42, 0x07, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x22, 0x9f, 0x01, 0x0a,
0x0d, 0x41, 0x75, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x12,
0x0a, 0x04, 0x72, 0x65, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x72, 0x65,
0x61, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28,
0x0c, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x65, 0x65, 0x64,
0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x73, 0x65, 0x65, 0x64, 0x12, 0x1e, 0x0a, 0x0a,
0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c,
0x52, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x05,
0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x72,
0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74,
0x6f, 0x72, 0x50, 0x72, 0x6f, 0x6f, 0x66, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x42, 0x3b,
0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x69, 0x67,
0x6e, 0x61, 0x6c, 0x61, 0x70, 0x70, 0x2f, 0x6b, 0x65, 0x79, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70,
0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2f, 0x74, 0x72, 0x65, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e,
0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x33,
}
var (
@ -1727,6 +1738,7 @@ func file_pb_transparency_proto_init() {
}
file_pb_transparency_proto_msgTypes[4].OneofWrappers = []any{}
file_pb_transparency_proto_msgTypes[9].OneofWrappers = []any{}
file_pb_transparency_proto_msgTypes[10].OneofWrappers = []any{}
file_pb_transparency_proto_msgTypes[18].OneofWrappers = []any{
(*AuditorProof_NewTree_)(nil),
(*AuditorProof_DifferentKey_)(nil),

View File

@ -82,6 +82,7 @@ message Consistency {
message TreeSearchRequest {
bytes search_key = 1;
Consistency consistency = 2;
optional uint32 version = 3;
}
// TreeSearchResponse is the output of executing a search on the tree.

View File

@ -108,21 +108,24 @@ func TestTreeWithAuditorHeads(t *testing.T) {
}
}
func TestTree(t *testing.T) {
func TestTreeSearchForVersion(t *testing.T) {
tree, store, _, _ := NewTree(t, transparency.ContactMonitoring)
var (
keys [][]byte
values [][]byte
repeatKey = random()
repeatKeyValues [][]byte
randomKeys [][]byte
randomKeyValues [][]byte
)
for i := 0; i < 100; i++ {
dice := mrand.Intn(4)
dice := mrand.Intn(5)
if dice == 0 && len(keys) > 0 { // Search for an existing key.
i := mrand.Intn(len(keys))
if dice == 0 && len(randomKeys) > 0 { // Search for an existing random key, most recent version.
i := mrand.Intn(len(randomKeys))
req := &pb.TreeSearchRequest{
SearchKey: keys[i],
SearchKey: randomKeys[i],
Consistency: Last(store),
}
res, err := tree.Search(req)
@ -130,10 +133,25 @@ func TestTree(t *testing.T) {
t.Fatal(err)
} else if err := transparency.VerifySearch(store, req, res); err != nil {
t.Fatal(err)
} else if !bytes.Equal(res.Value.Value, values[i]) {
} else if !bytes.Equal(res.Value.Value, randomKeyValues[i]) {
t.Fatal("unexpected value returned")
}
} else if dice == 1 { // Add a new key.
} else if dice == 1 && len(repeatKeyValues) > 0 { // Search for a specific version of the repeat key
version := uint32(mrand.Intn(len(repeatKeyValues)))
req := &pb.TreeSearchRequest{
SearchKey: repeatKey,
Consistency: Last(store),
Version: &version,
}
res, err := tree.Search(req)
if err != nil {
t.Fatal(err)
} else if err := transparency.VerifySearch(store, req, res); err != nil {
t.Fatal(err)
} else if !bytes.Equal(res.Value.Value, repeatKeyValues[version]) {
t.Fatal("unexpected value returned")
}
} else if dice == 2 { // Add a new random key.
key, value := random(), random()
req := &pb.UpdateRequest{
SearchKey: key,
@ -146,11 +164,11 @@ func TestTree(t *testing.T) {
} else if err := transparency.VerifyUpdate(store, req, res); err != nil {
t.Fatal(err)
}
keys, values = append(keys, key), append(values, value)
} else if dice == 2 && len(keys) > 0 { // Update an existing key.
i, value := mrand.Intn(len(keys)), random()
randomKeys, randomKeyValues = append(randomKeys, key), append(randomKeyValues, value)
} else if dice == 3 && len(randomKeys) > 0 { // Update the repeat key
value := random()
req := &pb.UpdateRequest{
SearchKey: keys[i],
SearchKey: repeatKey,
Value: value,
Consistency: Last(store),
}
@ -160,8 +178,8 @@ func TestTree(t *testing.T) {
} else if err := transparency.VerifyUpdate(store, req, res); err != nil {
t.Fatal(err)
}
values[i] = value
} else if dice == 3 && len(keys) > 0 { // Add some fake updates.
repeatKeyValues = append(repeatKeyValues, value)
} else if dice == 4 && (len(randomKeys) > 0 || len(repeatKeyValues) > 0) { // Add some fake updates.
if err := tree.BatchUpdateFake(5); err != nil {
t.Fatal(err)
}

View File

@ -238,9 +238,9 @@ func (t *Tree) updatedAuditorHeads(treeSize uint64) (map[string]*db.AuditorTreeH
return auditors, nil
}
func (t *Tree) search(index [32]byte, firstUpdatePosition, latestUpdatePosition uint64) (*pb.SearchProof, error) {
func (t *Tree) search(index [32]byte, firstUpdatePosition, latestUpdatePosition uint64, mostRecent bool) (*pb.SearchProof, error) {
// Determine the path of our binary search.
ids, err := searchPath(firstUpdatePosition, latestUpdatePosition, t.latest.TreeSize)
ids, err := searchPath(firstUpdatePosition, latestUpdatePosition, t.latest.TreeSize, mostRecent)
if err != nil {
return nil, err
}
@ -294,20 +294,27 @@ func (t *Tree) Search(req *pb.TreeSearchRequest) (*pb.TreeSearchResponse, error)
index, vrfProof := t.config.VrfKey.ECVRFProve(req.SearchKey)
// Find the position of the first occurrence of the index in the log, and the
// position of the most recent occurrence of the index in the log.
var firstUpdatePosition, latestUpdatePosition uint64
res, err := t.prefixTree.Search(t.latest.TreeSize, index[:])
// position of the most recent occurrence of the index in the log OR the
// position corresponding to the requested version.
var res *prefix.SearchResult
var err error
if req.Version == nil {
res, err = t.prefixTree.Search(t.latest.TreeSize, index[:])
} else {
res, err = t.prefixTree.SearchForVersion(t.latest.TreeSize, index[:], *req.Version)
}
if err != nil {
return nil, err
}
firstUpdatePosition, latestUpdatePosition = res.FirstUpdatePosition, res.LatestUpdatePosition
firstUpdatePosition, updatePosition := res.FirstUpdatePosition, res.LatestUpdatePosition
// Fetch the search proof and the update value.
searchProof, err := t.search(index, firstUpdatePosition, latestUpdatePosition)
searchProof, err := t.search(index, firstUpdatePosition, updatePosition, req.Version == nil)
if err != nil {
return nil, err
}
raw, err := t.tx.Get(latestUpdatePosition)
raw, err := t.tx.Get(updatePosition)
if err != nil {
return nil, err
}
@ -326,7 +333,7 @@ func (t *Tree) Search(req *pb.TreeSearchRequest) (*pb.TreeSearchResponse, error)
VrfProof: vrfProof,
Search: searchProof,
Opening: computeOpening(t.config.OpeningKey, latestUpdatePosition),
Opening: computeOpening(t.config.OpeningKey, updatePosition),
Value: value,
}, nil
}
@ -378,7 +385,7 @@ func (t *Tree) PostUpdate(state *PostUpdateState) (*pb.UpdateResponse, error) {
t.latest = state.head
// Build a search proof for the newly-added value.
searchProof, err := t.search(state.pre.index, state.sr.FirstUpdatePosition, state.sr.LatestUpdatePosition)
searchProof, err := t.search(state.pre.index, state.sr.FirstUpdatePosition, state.sr.LatestUpdatePosition, true)
if err != nil {
return nil, err
}
@ -902,14 +909,24 @@ func (t *Tree) SetAuditorHead(head *pb.AuditorTreeHead, auditorName string) erro
}
// searchPath returns the set of ids that will be accessed by a binary search
// through the transparency tree. `firstUpdatePosition` is the position of the first
// occurrence of the index in the tree, `latestUpdatePosition` is the position of the most recent occurrence
// of the index in the tree, and `treeSize` is the current size of the tree.
func searchPath(firstUpdatePosition, latestUpdatePosition, treeSize uint64) ([]uint64, error) {
// through the transparency tree for the entry associated with `latestUpdatePosition`.
// `firstUpdatePosition` is the position of the first occurrence of the index in the tree,
// `latestUpdatePosition` is the position of the most recent occurrence of the index in the tree, and
// `treeSize` is the current size of the tree.
func searchPath(firstUpdatePosition, latestUpdatePosition, treeSize uint64, mostRecent bool) ([]uint64, error) {
var ids []uint64
var guide *proofGuide
guide = mostRecentProofGuide(firstUpdatePosition, treeSize)
if mostRecent {
// The target counter is always 1, but the proof guide for the most recent version has to "prove" this by
// first searching the frontier nodes of the implicit binary search tree instead of hardcoding it like
// the versioned proof guide.
guide = mostRecentProofGuide(firstUpdatePosition, treeSize)
} else {
guide = versionProofGuide(1, firstUpdatePosition, treeSize)
}
for {
done, err := guide.done()
if err != nil {

View File

@ -178,7 +178,11 @@ func verifySearch(storage ClientStorage, req *pb.TreeSearchRequest, res *pb.Tree
stepMap := make(map[uint64]*pb.ProofStep)
var guide *proofGuide
guide = mostRecentProofGuide(res.Search.Pos, treeSize)
if req.Version == nil {
guide = mostRecentProofGuide(res.Search.Pos, treeSize)
} else {
guide = versionProofGuide(*req.Version, res.Search.Pos, treeSize)
}
for {
done, err := guide.done()
if err != nil {
@ -190,6 +194,8 @@ func verifySearch(storage ClientStorage, req *pb.TreeSearchRequest, res *pb.Tree
}
id := guide.next()
step := res.Search.Steps[i]
// Unlike during search proof generation, we use the actual version of the index during search proof verification.
guide.insert(id, step.Prefix.Counter)
// Evaluate the prefix proof and combine it with the commitment to get