Search for a specific version of an identifier
Some checks failed
CI / test (push) Has been cancelled
Some checks failed
CI / test (push) Has been cancelled
This commit is contained in:
parent
e1df58749d
commit
e5a45343df
@ -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")
|
||||
|
||||
@ -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.")
|
||||
)
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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")
|
||||
}
|
||||
|
||||
@ -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 (
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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++ {
|
||||
|
||||
@ -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")
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user