Merge pull request #3556 from joostjager/query-mc-prob

routerrpc: add queryprob rpc
This commit is contained in:
Joost Jager 2019-10-31 08:03:29 +01:00 committed by GitHub
commit fcf81ed8ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 582 additions and 204 deletions

@ -48,9 +48,9 @@ func queryMissionControl(ctx *cli.Context) error {
displayPairHistory{
NodeFrom: hex.EncodeToString(n.NodeFrom),
NodeTo: hex.EncodeToString(n.NodeTo),
LastAttemptSuccessful: n.LastAttemptSuccessful,
Timestamp: n.Timestamp,
MinPenalizeAmtSat: n.MinPenalizeAmtSat,
LastAttemptSuccessful: n.History.LastAttemptSuccessful,
Timestamp: n.History.Timestamp,
MinPenalizeAmtSat: n.History.MinPenalizeAmtSat,
},
)
}

@ -0,0 +1,70 @@
// +build routerrpc
package main
import (
"context"
"fmt"
"strconv"
"github.com/btcsuite/btcutil"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing/route"
"github.com/urfave/cli"
)
var queryProbCommand = cli.Command{
Name: "queryprob",
Category: "Payments",
Usage: "Estimate a success probability.",
ArgsUsage: "from-node to-node amt",
Action: actionDecorator(queryProb),
}
func queryProb(ctx *cli.Context) error {
args := ctx.Args()
if len(args) != 3 {
return cli.ShowCommandHelp(ctx, "queryprob")
}
fromNode, err := route.NewVertexFromStr(args.Get(0))
if err != nil {
return fmt.Errorf("invalid from node key: %v", err)
}
toNode, err := route.NewVertexFromStr(args.Get(1))
if err != nil {
return fmt.Errorf("invalid to node key: %v", err)
}
amtSat, err := strconv.ParseUint(args.Get(2), 10, 64)
if err != nil {
return fmt.Errorf("invalid amt: %v", err)
}
amtMsat := lnwire.NewMSatFromSatoshis(
btcutil.Amount(amtSat),
)
conn := getClientConn(ctx, false)
defer conn.Close()
client := routerrpc.NewRouterClient(conn)
req := &routerrpc.QueryProbabilityRequest{
FromNode: fromNode[:],
ToNode: toNode[:],
AmtMsat: int64(amtMsat),
}
rpcCtx := context.Background()
response, err := client.QueryProbability(rpcCtx, req)
if err != nil {
return err
}
printJSON(response)
return nil
}

@ -8,6 +8,7 @@ import "github.com/urfave/cli"
func routerCommands() []cli.Command {
return []cli.Command{
queryMissionControlCommand,
queryProbCommand,
resetMissionControlCommand,
buildRouteCommand,
}

@ -1051,12 +1051,7 @@ type PairHistory struct {
NodeFrom []byte `protobuf:"bytes,1,opt,name=node_from,proto3" json:"node_from,omitempty"`
/// The destination node pubkey of the pair.
NodeTo []byte `protobuf:"bytes,2,opt,name=node_to,proto3" json:"node_to,omitempty"`
/// Time stamp of last result.
Timestamp int64 `protobuf:"varint,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
/// Minimum penalization amount (only applies to failed attempts).
MinPenalizeAmtSat int64 `protobuf:"varint,4,opt,name=min_penalize_amt_sat,proto3" json:"min_penalize_amt_sat,omitempty"`
/// Whether the last payment attempt through this pair was successful.
LastAttemptSuccessful bool `protobuf:"varint,6,opt,name=last_attempt_successful,proto3" json:"last_attempt_successful,omitempty"`
History *PairData `protobuf:"bytes,7,opt,name=history,proto3" json:"history,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -1101,27 +1096,178 @@ func (m *PairHistory) GetNodeTo() []byte {
return nil
}
func (m *PairHistory) GetTimestamp() int64 {
func (m *PairHistory) GetHistory() *PairData {
if m != nil {
return m.History
}
return nil
}
type PairData struct {
/// Time stamp of last result.
Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
/// Minimum penalization amount (only applies to failed attempts).
MinPenalizeAmtSat int64 `protobuf:"varint,2,opt,name=min_penalize_amt_sat,proto3" json:"min_penalize_amt_sat,omitempty"`
/// Whether the last payment attempt through this pair was successful.
LastAttemptSuccessful bool `protobuf:"varint,3,opt,name=last_attempt_successful,proto3" json:"last_attempt_successful,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *PairData) Reset() { *m = PairData{} }
func (m *PairData) String() string { return proto.CompactTextString(m) }
func (*PairData) ProtoMessage() {}
func (*PairData) Descriptor() ([]byte, []int) {
return fileDescriptor_7a0613f69d37b0a5, []int{14}
}
func (m *PairData) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_PairData.Unmarshal(m, b)
}
func (m *PairData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_PairData.Marshal(b, m, deterministic)
}
func (m *PairData) XXX_Merge(src proto.Message) {
xxx_messageInfo_PairData.Merge(m, src)
}
func (m *PairData) XXX_Size() int {
return xxx_messageInfo_PairData.Size(m)
}
func (m *PairData) XXX_DiscardUnknown() {
xxx_messageInfo_PairData.DiscardUnknown(m)
}
var xxx_messageInfo_PairData proto.InternalMessageInfo
func (m *PairData) GetTimestamp() int64 {
if m != nil {
return m.Timestamp
}
return 0
}
func (m *PairHistory) GetMinPenalizeAmtSat() int64 {
func (m *PairData) GetMinPenalizeAmtSat() int64 {
if m != nil {
return m.MinPenalizeAmtSat
}
return 0
}
func (m *PairHistory) GetLastAttemptSuccessful() bool {
func (m *PairData) GetLastAttemptSuccessful() bool {
if m != nil {
return m.LastAttemptSuccessful
}
return false
}
type QueryProbabilityRequest struct {
/// The source node pubkey of the pair.
FromNode []byte `protobuf:"bytes,1,opt,name=from_node,proto3" json:"from_node,omitempty"`
/// The destination node pubkey of the pair.
ToNode []byte `protobuf:"bytes,2,opt,name=to_node,proto3" json:"to_node,omitempty"`
/// The amount for which to calculate a probability.
AmtMsat int64 `protobuf:"varint,3,opt,name=amt_msat,proto3" json:"amt_msat,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *QueryProbabilityRequest) Reset() { *m = QueryProbabilityRequest{} }
func (m *QueryProbabilityRequest) String() string { return proto.CompactTextString(m) }
func (*QueryProbabilityRequest) ProtoMessage() {}
func (*QueryProbabilityRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_7a0613f69d37b0a5, []int{15}
}
func (m *QueryProbabilityRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_QueryProbabilityRequest.Unmarshal(m, b)
}
func (m *QueryProbabilityRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_QueryProbabilityRequest.Marshal(b, m, deterministic)
}
func (m *QueryProbabilityRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_QueryProbabilityRequest.Merge(m, src)
}
func (m *QueryProbabilityRequest) XXX_Size() int {
return xxx_messageInfo_QueryProbabilityRequest.Size(m)
}
func (m *QueryProbabilityRequest) XXX_DiscardUnknown() {
xxx_messageInfo_QueryProbabilityRequest.DiscardUnknown(m)
}
var xxx_messageInfo_QueryProbabilityRequest proto.InternalMessageInfo
func (m *QueryProbabilityRequest) GetFromNode() []byte {
if m != nil {
return m.FromNode
}
return nil
}
func (m *QueryProbabilityRequest) GetToNode() []byte {
if m != nil {
return m.ToNode
}
return nil
}
func (m *QueryProbabilityRequest) GetAmtMsat() int64 {
if m != nil {
return m.AmtMsat
}
return 0
}
type QueryProbabilityResponse struct {
/// The success probability for the requested pair.
Probability float64 `protobuf:"fixed64,1,opt,name=probability,proto3" json:"probability,omitempty"`
/// The historical data for the requested pair.
History *PairData `protobuf:"bytes,2,opt,name=history,proto3" json:"history,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *QueryProbabilityResponse) Reset() { *m = QueryProbabilityResponse{} }
func (m *QueryProbabilityResponse) String() string { return proto.CompactTextString(m) }
func (*QueryProbabilityResponse) ProtoMessage() {}
func (*QueryProbabilityResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_7a0613f69d37b0a5, []int{16}
}
func (m *QueryProbabilityResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_QueryProbabilityResponse.Unmarshal(m, b)
}
func (m *QueryProbabilityResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_QueryProbabilityResponse.Marshal(b, m, deterministic)
}
func (m *QueryProbabilityResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_QueryProbabilityResponse.Merge(m, src)
}
func (m *QueryProbabilityResponse) XXX_Size() int {
return xxx_messageInfo_QueryProbabilityResponse.Size(m)
}
func (m *QueryProbabilityResponse) XXX_DiscardUnknown() {
xxx_messageInfo_QueryProbabilityResponse.DiscardUnknown(m)
}
var xxx_messageInfo_QueryProbabilityResponse proto.InternalMessageInfo
func (m *QueryProbabilityResponse) GetProbability() float64 {
if m != nil {
return m.Probability
}
return 0
}
func (m *QueryProbabilityResponse) GetHistory() *PairData {
if m != nil {
return m.History
}
return nil
}
type BuildRouteRequest struct {
//*
//The amount to send expressed in msat. If set to zero, the minimum routable
@ -1148,7 +1294,7 @@ func (m *BuildRouteRequest) Reset() { *m = BuildRouteRequest{} }
func (m *BuildRouteRequest) String() string { return proto.CompactTextString(m) }
func (*BuildRouteRequest) ProtoMessage() {}
func (*BuildRouteRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_7a0613f69d37b0a5, []int{14}
return fileDescriptor_7a0613f69d37b0a5, []int{17}
}
func (m *BuildRouteRequest) XXX_Unmarshal(b []byte) error {
@ -1210,7 +1356,7 @@ func (m *BuildRouteResponse) Reset() { *m = BuildRouteResponse{} }
func (m *BuildRouteResponse) String() string { return proto.CompactTextString(m) }
func (*BuildRouteResponse) ProtoMessage() {}
func (*BuildRouteResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_7a0613f69d37b0a5, []int{15}
return fileDescriptor_7a0613f69d37b0a5, []int{18}
}
func (m *BuildRouteResponse) XXX_Unmarshal(b []byte) error {
@ -1256,6 +1402,9 @@ func init() {
proto.RegisterType((*QueryMissionControlRequest)(nil), "routerrpc.QueryMissionControlRequest")
proto.RegisterType((*QueryMissionControlResponse)(nil), "routerrpc.QueryMissionControlResponse")
proto.RegisterType((*PairHistory)(nil), "routerrpc.PairHistory")
proto.RegisterType((*PairData)(nil), "routerrpc.PairData")
proto.RegisterType((*QueryProbabilityRequest)(nil), "routerrpc.QueryProbabilityRequest")
proto.RegisterType((*QueryProbabilityResponse)(nil), "routerrpc.QueryProbabilityResponse")
proto.RegisterType((*BuildRouteRequest)(nil), "routerrpc.BuildRouteRequest")
proto.RegisterType((*BuildRouteResponse)(nil), "routerrpc.BuildRouteResponse")
}
@ -1263,120 +1412,128 @@ func init() {
func init() { proto.RegisterFile("routerrpc/router.proto", fileDescriptor_7a0613f69d37b0a5) }
var fileDescriptor_7a0613f69d37b0a5 = []byte{
// 1805 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x57, 0x4f, 0x73, 0x1a, 0xc9,
0x15, 0xdf, 0x11, 0x20, 0xe0, 0x01, 0xd2, 0xa8, 0x25, 0xcb, 0x63, 0x64, 0xad, 0xb5, 0xec, 0x66,
0x57, 0xe5, 0x72, 0x24, 0x47, 0xa9, 0xdd, 0x72, 0xed, 0x21, 0x29, 0x0c, 0xcd, 0x6a, 0x6c, 0x98,
0x91, 0x1b, 0xf0, 0xae, 0x93, 0x43, 0x57, 0x1b, 0x5a, 0x62, 0x4a, 0xc3, 0x0c, 0x3b, 0xd3, 0x38,
0x56, 0x0e, 0xa9, 0xca, 0x07, 0xc8, 0xe7, 0xc8, 0x25, 0xb7, 0x7c, 0x91, 0xdc, 0xf2, 0x0d, 0x92,
0x4f, 0x90, 0x7b, 0xaa, 0xbb, 0x67, 0x60, 0x90, 0x90, 0x93, 0x93, 0xe8, 0xdf, 0xfb, 0xd7, 0xf3,
0xde, 0xeb, 0xdf, 0x7b, 0x82, 0xfd, 0x28, 0x9c, 0x0b, 0x1e, 0x45, 0xb3, 0xd1, 0xa9, 0xfe, 0x75,
0x32, 0x8b, 0x42, 0x11, 0xa2, 0xf2, 0x02, 0xaf, 0x97, 0xa3, 0xd9, 0x48, 0xa3, 0x8d, 0x3f, 0xe7,
0x01, 0xf5, 0x79, 0x30, 0xbe, 0x60, 0x37, 0x53, 0x1e, 0x08, 0xc2, 0x7f, 0x9e, 0xf3, 0x58, 0x20,
0x04, 0xf9, 0x31, 0x8f, 0x85, 0x65, 0x1c, 0x19, 0xc7, 0x55, 0xa2, 0x7e, 0x23, 0x13, 0x72, 0x6c,
0x2a, 0xac, 0x8d, 0x23, 0xe3, 0x38, 0x47, 0xe4, 0x4f, 0xf4, 0x05, 0x54, 0x67, 0xda, 0x8e, 0x4e,
0x58, 0x3c, 0xb1, 0x72, 0x4a, 0xbb, 0x92, 0x60, 0xe7, 0x2c, 0x9e, 0xa0, 0x63, 0x30, 0x2f, 0xbd,
0x80, 0xf9, 0x74, 0xe4, 0x8b, 0x0f, 0x74, 0xcc, 0x7d, 0xc1, 0xac, 0xfc, 0x91, 0x71, 0x5c, 0x20,
0x5b, 0x0a, 0x6f, 0xf9, 0xe2, 0x43, 0x5b, 0xa2, 0xe8, 0x1b, 0xd8, 0x4e, 0x9d, 0x45, 0xfa, 0x16,
0x56, 0xe1, 0xc8, 0x38, 0x2e, 0x93, 0xad, 0xd9, 0xea, 0xdd, 0xbe, 0x81, 0x6d, 0xe1, 0x4d, 0x79,
0x38, 0x17, 0x34, 0xe6, 0xa3, 0x30, 0x18, 0xc7, 0xd6, 0xa6, 0xf6, 0x98, 0xc0, 0x7d, 0x8d, 0xa2,
0x06, 0xd4, 0x2e, 0x39, 0xa7, 0xbe, 0x37, 0xf5, 0x04, 0x8d, 0x99, 0xb0, 0x8a, 0xea, 0xea, 0x95,
0x4b, 0xce, 0xbb, 0x12, 0xeb, 0x33, 0x81, 0x9e, 0x81, 0x19, 0xce, 0xc5, 0x55, 0xe8, 0x05, 0x57,
0x74, 0x34, 0x61, 0x01, 0xf5, 0xc6, 0x56, 0xe9, 0xc8, 0x38, 0xce, 0xbf, 0xdc, 0x78, 0x6e, 0x90,
0xad, 0x54, 0xd6, 0x9a, 0xb0, 0xc0, 0x1e, 0xa3, 0x43, 0x00, 0xf5, 0x1d, 0xca, 0xa5, 0x55, 0x56,
0x51, 0xcb, 0x12, 0x51, 0xfe, 0xd0, 0x19, 0x54, 0x54, 0x92, 0xe9, 0xc4, 0x0b, 0x44, 0x6c, 0xc1,
0x51, 0xee, 0xb8, 0x72, 0x66, 0x9e, 0xf8, 0x81, 0xcc, 0x37, 0x91, 0x92, 0x73, 0x2f, 0x10, 0x24,
0xab, 0x84, 0x30, 0x94, 0x64, 0x76, 0xa9, 0xf0, 0x3f, 0x58, 0x15, 0x65, 0xf0, 0xf4, 0x64, 0x51,
0xa9, 0x93, 0xbb, 0xa5, 0x39, 0x69, 0xf3, 0x58, 0x0c, 0xfc, 0x0f, 0x38, 0x10, 0xd1, 0x0d, 0x29,
0x8e, 0xf5, 0xa9, 0xfe, 0x3d, 0x54, 0xb3, 0x02, 0x59, 0xac, 0x6b, 0x7e, 0xa3, 0xea, 0x97, 0x27,
0xf2, 0x27, 0xda, 0x83, 0xc2, 0x07, 0xe6, 0xcf, 0xb9, 0x2a, 0x60, 0x95, 0xe8, 0xc3, 0xf7, 0x1b,
0x2f, 0x8c, 0xc6, 0x0b, 0xd8, 0x1d, 0x44, 0x6c, 0x74, 0x7d, 0xab, 0x07, 0x6e, 0x57, 0xd7, 0xb8,
0x53, 0xdd, 0xc6, 0x9f, 0xa0, 0x96, 0x18, 0xf5, 0x05, 0x13, 0xf3, 0x18, 0xfd, 0x12, 0x0a, 0xb1,
0x60, 0x82, 0x2b, 0xe5, 0xad, 0xb3, 0x87, 0x99, 0x4f, 0xc9, 0x28, 0x72, 0xa2, 0xb5, 0x50, 0x1d,
0x4a, 0xb3, 0x88, 0x7b, 0x53, 0x76, 0x95, 0x5e, 0x6b, 0x71, 0x46, 0x0d, 0x28, 0x28, 0x63, 0xd5,
0x55, 0x95, 0xb3, 0x6a, 0x36, 0x8d, 0x44, 0x8b, 0x1a, 0xbf, 0x81, 0x6d, 0x75, 0xee, 0x70, 0xfe,
0xa9, 0xce, 0x7d, 0x08, 0x45, 0x36, 0xd5, 0x2d, 0xa0, 0xbb, 0x77, 0x93, 0x4d, 0x65, 0xf5, 0x1b,
0x63, 0x30, 0x97, 0xf6, 0xf1, 0x2c, 0x0c, 0x62, 0x2e, 0x3b, 0x56, 0x3a, 0x97, 0x0d, 0x21, 0xbb,
0x67, 0x2a, 0xad, 0x0c, 0x65, 0xb5, 0x95, 0xe0, 0x1d, 0xce, 0x7b, 0x31, 0x13, 0xe8, 0x6b, 0xdd,
0x88, 0xd4, 0x0f, 0x47, 0xd7, 0xb2, 0xb5, 0xd9, 0x4d, 0xe2, 0xbe, 0x26, 0xe1, 0x6e, 0x38, 0xba,
0x6e, 0x4b, 0xb0, 0xf1, 0x7b, 0xfd, 0xc4, 0x06, 0xa1, 0xbe, 0xfb, 0xff, 0x9d, 0xde, 0x65, 0x0a,
0x36, 0xee, 0x4f, 0x01, 0x85, 0xdd, 0x15, 0xe7, 0xc9, 0x57, 0x64, 0x33, 0x6b, 0xdc, 0xca, 0xec,
0x33, 0x28, 0x5e, 0x32, 0xcf, 0x9f, 0x47, 0xa9, 0x63, 0x94, 0x29, 0x53, 0x47, 0x4b, 0x48, 0xaa,
0xd2, 0xf8, 0x4f, 0x11, 0x8a, 0x09, 0x88, 0xce, 0x20, 0x3f, 0x0a, 0xc7, 0x69, 0x75, 0x3f, 0xbf,
0x6b, 0x96, 0xfe, 0x6d, 0x85, 0x63, 0x4e, 0x94, 0x2e, 0xfa, 0x2d, 0x6c, 0xc9, 0x87, 0x15, 0x70,
0x9f, 0xce, 0x67, 0x63, 0xb6, 0x28, 0xa8, 0x95, 0xb1, 0x6e, 0x69, 0x85, 0xa1, 0x92, 0x93, 0xda,
0x28, 0x7b, 0x44, 0x07, 0x50, 0x9e, 0x08, 0x7f, 0xa4, 0x2b, 0x91, 0x57, 0x0d, 0x5d, 0x92, 0x80,
0xaa, 0x41, 0x03, 0x6a, 0x61, 0xe0, 0x85, 0x01, 0x8d, 0x27, 0x8c, 0x9e, 0x7d, 0xfb, 0x9d, 0xe2,
0x8c, 0x2a, 0xa9, 0x28, 0xb0, 0x3f, 0x61, 0x67, 0xdf, 0x7e, 0x87, 0x9e, 0x40, 0x45, 0xbd, 0x5a,
0xfe, 0x71, 0xe6, 0x45, 0x37, 0x8a, 0x2c, 0x6a, 0x44, 0x3d, 0x64, 0xac, 0x10, 0xf9, 0x34, 0x2e,
0x7d, 0x76, 0x15, 0x2b, 0x82, 0xa8, 0x11, 0x7d, 0x40, 0xcf, 0x61, 0x2f, 0xc9, 0x01, 0x8d, 0xc3,
0x79, 0x34, 0xe2, 0xd4, 0x0b, 0xc6, 0xfc, 0xa3, 0xa2, 0x87, 0x1a, 0x41, 0x89, 0xac, 0xaf, 0x44,
0xb6, 0x94, 0xa0, 0x7d, 0xd8, 0x9c, 0x70, 0xef, 0x6a, 0xa2, 0xa9, 0xa1, 0x46, 0x92, 0x53, 0xe3,
0x6f, 0x05, 0xa8, 0x64, 0x12, 0x83, 0xaa, 0x50, 0x22, 0xb8, 0x8f, 0xc9, 0x5b, 0xdc, 0x36, 0x3f,
0x43, 0xc7, 0xf0, 0x95, 0xed, 0xb4, 0x5c, 0x42, 0x70, 0x6b, 0x40, 0x5d, 0x42, 0x87, 0xce, 0x6b,
0xc7, 0xfd, 0xd1, 0xa1, 0x17, 0xcd, 0x77, 0x3d, 0xec, 0x0c, 0x68, 0x1b, 0x0f, 0x9a, 0x76, 0xb7,
0x6f, 0x1a, 0xe8, 0x31, 0x58, 0x4b, 0xcd, 0x54, 0xdc, 0xec, 0xb9, 0x43, 0x67, 0x60, 0x6e, 0xa0,
0x27, 0x70, 0xd0, 0xb1, 0x9d, 0x66, 0x97, 0x2e, 0x75, 0x5a, 0xdd, 0xc1, 0x5b, 0x8a, 0x7f, 0xba,
0xb0, 0xc9, 0x3b, 0x33, 0xb7, 0x4e, 0xe1, 0x7c, 0xd0, 0x6d, 0xa5, 0x1e, 0xf2, 0xe8, 0x11, 0x3c,
0xd0, 0x0a, 0xda, 0x84, 0x0e, 0x5c, 0x97, 0xf6, 0x5d, 0xd7, 0x31, 0x0b, 0x68, 0x07, 0x6a, 0xb6,
0xf3, 0xb6, 0xd9, 0xb5, 0xdb, 0x94, 0xe0, 0x66, 0xb7, 0x67, 0x6e, 0xa2, 0x5d, 0xd8, 0xbe, 0xad,
0x57, 0x94, 0x2e, 0x52, 0x3d, 0xd7, 0xb1, 0x5d, 0x87, 0xbe, 0xc5, 0xa4, 0x6f, 0xbb, 0x8e, 0x59,
0x42, 0xfb, 0x80, 0x56, 0x45, 0xe7, 0xbd, 0x66, 0xcb, 0x2c, 0xa3, 0x07, 0xb0, 0xb3, 0x8a, 0xbf,
0xc6, 0xef, 0x4c, 0x40, 0x16, 0xec, 0xe9, 0x8b, 0xd1, 0x97, 0xb8, 0xeb, 0xfe, 0x48, 0x7b, 0xb6,
0x63, 0xf7, 0x86, 0x3d, 0xb3, 0x82, 0xf6, 0xc0, 0xec, 0x60, 0x4c, 0x6d, 0xa7, 0x3f, 0xec, 0x74,
0xec, 0x96, 0x8d, 0x9d, 0x81, 0x59, 0xd5, 0x91, 0xd7, 0x7d, 0x78, 0x4d, 0x1a, 0xb4, 0xce, 0x9b,
0x8e, 0x83, 0xbb, 0xb4, 0x6d, 0xf7, 0x9b, 0x2f, 0xbb, 0xb8, 0x6d, 0x6e, 0xa1, 0x43, 0x78, 0x34,
0xc0, 0xbd, 0x0b, 0x97, 0x34, 0xc9, 0x3b, 0x9a, 0xca, 0x3b, 0x4d, 0xbb, 0x3b, 0x24, 0xd8, 0xdc,
0x46, 0x5f, 0xc0, 0x21, 0xc1, 0x6f, 0x86, 0x36, 0xc1, 0x6d, 0xea, 0xb8, 0x6d, 0x4c, 0x3b, 0xb8,
0x39, 0x18, 0x12, 0x4c, 0x7b, 0x76, 0xbf, 0x6f, 0x3b, 0x3f, 0x98, 0x26, 0xfa, 0x0a, 0x8e, 0x16,
0x2a, 0x0b, 0x07, 0xb7, 0xb4, 0x76, 0xe4, 0xf7, 0xa5, 0x25, 0x75, 0xf0, 0x4f, 0x03, 0x7a, 0x81,
0x31, 0x31, 0x11, 0xaa, 0xc3, 0xfe, 0x32, 0xbc, 0x0e, 0x90, 0xc4, 0xde, 0x95, 0xb2, 0x0b, 0x4c,
0x7a, 0x4d, 0x47, 0x16, 0x78, 0x45, 0xb6, 0x27, 0xaf, 0xbd, 0x94, 0xdd, 0xbe, 0xf6, 0x03, 0x84,
0x60, 0x2b, 0x53, 0x95, 0x4e, 0x93, 0x98, 0xfb, 0x68, 0x0f, 0xb6, 0xd3, 0x1b, 0xa4, 0x8a, 0xff,
0x2a, 0xa2, 0x87, 0x80, 0x86, 0x0e, 0xc1, 0xcd, 0xb6, 0x4c, 0xc8, 0x42, 0xf0, 0xef, 0xe2, 0xab,
0x7c, 0x69, 0xc3, 0xcc, 0x35, 0xfe, 0x9e, 0x83, 0xda, 0xca, 0xbb, 0x44, 0x8f, 0xa1, 0x1c, 0x7b,
0x57, 0x01, 0x13, 0x92, 0x39, 0x34, 0xa9, 0x2c, 0x01, 0x35, 0x1b, 0x27, 0xcc, 0x0b, 0x34, 0x9b,
0x69, 0x36, 0x2f, 0x2b, 0x44, 0x71, 0xd9, 0x01, 0x14, 0xd3, 0xf9, 0x9a, 0x5b, 0xcc, 0xd7, 0xcd,
0x91, 0x9e, 0xab, 0x8f, 0xa1, 0x2c, 0x29, 0x33, 0x16, 0x6c, 0x3a, 0x53, 0x4f, 0xbc, 0x46, 0x96,
0x00, 0xfa, 0x12, 0x6a, 0x53, 0x1e, 0xc7, 0xec, 0x8a, 0x53, 0xfd, 0x4c, 0x41, 0x69, 0x54, 0x13,
0xb0, 0xa3, 0x5e, 0xeb, 0x97, 0x90, 0xd2, 0x46, 0xa2, 0x54, 0xd0, 0x4a, 0x09, 0xa8, 0x95, 0x6e,
0x33, 0xb6, 0x60, 0x09, 0x1b, 0x64, 0x19, 0x5b, 0x30, 0xf4, 0x14, 0x76, 0x34, 0xe5, 0x78, 0x81,
0x37, 0x9d, 0x4f, 0x35, 0xf5, 0x14, 0x15, 0xf5, 0x6c, 0x2b, 0xea, 0xd1, 0xb8, 0x62, 0xa0, 0x47,
0x50, 0x7a, 0xcf, 0x62, 0x2e, 0x87, 0x45, 0x42, 0x0d, 0x45, 0x79, 0xee, 0x70, 0x2e, 0x45, 0x72,
0x84, 0x44, 0x92, 0xf4, 0x34, 0x23, 0x14, 0x2f, 0x39, 0x27, 0x32, 0x97, 0x8b, 0x08, 0xec, 0xe3,
0x32, 0x42, 0x25, 0x13, 0x41, 0xe3, 0x2a, 0xc2, 0x53, 0xd8, 0xe1, 0x1f, 0x45, 0xc4, 0x68, 0x38,
0x63, 0x3f, 0xcf, 0x39, 0x1d, 0x33, 0xc1, 0xac, 0xaa, 0x4a, 0xf0, 0xb6, 0x12, 0xb8, 0x0a, 0x6f,
0x33, 0xc1, 0x1a, 0x8f, 0xa1, 0x4e, 0x78, 0xcc, 0x45, 0xcf, 0x8b, 0x63, 0x2f, 0x0c, 0x5a, 0x61,
0x20, 0xa2, 0xd0, 0x4f, 0x66, 0x4e, 0xe3, 0x10, 0x0e, 0xd6, 0x4a, 0xf5, 0xd0, 0x90, 0xc6, 0x6f,
0xe6, 0x3c, 0xba, 0x59, 0x6f, 0xfc, 0x06, 0x0e, 0xd6, 0x4a, 0x93, 0x89, 0xf3, 0x0c, 0x0a, 0x33,
0xe6, 0x45, 0xb1, 0xb5, 0xa1, 0xb6, 0x98, 0xfd, 0x95, 0xd1, 0xef, 0x45, 0xe7, 0x5e, 0x2c, 0xc2,
0xe8, 0x86, 0x68, 0xa5, 0x57, 0xf9, 0x92, 0x61, 0x6e, 0x34, 0xfe, 0x69, 0x40, 0x25, 0x23, 0x94,
0x7d, 0x10, 0x84, 0x63, 0x4e, 0x2f, 0xa3, 0x70, 0x9a, 0x76, 0xd8, 0x02, 0x40, 0x16, 0x14, 0xd5,
0x41, 0x84, 0x49, 0x7b, 0xa5, 0xc7, 0xd5, 0xfe, 0xc9, 0xa9, 0x19, 0x9c, 0xe9, 0x9f, 0x33, 0xd8,
0x9b, 0x7a, 0x01, 0x9d, 0xf1, 0x80, 0xf9, 0xde, 0x1f, 0x39, 0x4d, 0x77, 0x81, 0xbc, 0x52, 0x5c,
0x2b, 0x43, 0x2f, 0xe0, 0xa1, 0xcf, 0x62, 0x41, 0x99, 0x10, 0x7c, 0x3a, 0x13, 0x34, 0x9e, 0x8f,
0x46, 0x3c, 0x8e, 0x2f, 0xe7, 0xbe, 0xea, 0x98, 0x12, 0xb9, 0x4f, 0xfc, 0x2a, 0x5f, 0x2a, 0x98,
0x9b, 0x8d, 0xbf, 0x1a, 0xb0, 0xf3, 0x72, 0xee, 0xf9, 0xe3, 0x95, 0x99, 0xff, 0x08, 0x4a, 0x32,
0x40, 0x66, 0xa7, 0x90, 0x8b, 0x89, 0x2a, 0xf2, 0xba, 0x45, 0x79, 0x63, 0xed, 0xa2, 0xbc, 0x6e,
0x65, 0xcd, 0xdd, 0xbb, 0xb2, 0x3e, 0x81, 0xca, 0x24, 0x9c, 0xd1, 0xd9, 0xfc, 0xfd, 0x35, 0xbf,
0x89, 0xad, 0xfc, 0x51, 0xee, 0xb8, 0x4a, 0x60, 0x12, 0xce, 0x2e, 0x34, 0xd2, 0x78, 0x01, 0x28,
0x7b, 0xd1, 0xa4, 0x9a, 0x8b, 0xd5, 0xc3, 0xb8, 0x77, 0xf5, 0x78, 0xfa, 0x17, 0x03, 0xaa, 0xd9,
0xad, 0x0e, 0xd5, 0xa0, 0x6c, 0x3b, 0xb4, 0xd3, 0xb5, 0x7f, 0x38, 0x1f, 0x98, 0x9f, 0xc9, 0x63,
0x7f, 0xd8, 0x6a, 0x61, 0xdc, 0xc6, 0x6d, 0xd3, 0x90, 0xcc, 0x24, 0x49, 0x06, 0xb7, 0xe9, 0xc0,
0xee, 0x61, 0x77, 0x28, 0x67, 0xd6, 0x2e, 0x6c, 0x27, 0x98, 0xe3, 0x52, 0xe2, 0x0e, 0x07, 0xd8,
0xcc, 0x21, 0x13, 0xaa, 0x09, 0x88, 0x09, 0x71, 0x89, 0x99, 0x97, 0x44, 0x9b, 0x20, 0x77, 0xe7,
0x5f, 0x3a, 0x1e, 0x0b, 0x67, 0xff, 0xc8, 0xc3, 0xa6, 0xba, 0x60, 0x84, 0xce, 0xa1, 0x92, 0x59,
0x9d, 0xd1, 0xe1, 0x27, 0x57, 0xea, 0xba, 0xb5, 0x7e, 0x4d, 0x9d, 0xc7, 0xcf, 0x0d, 0xf4, 0x0a,
0xaa, 0xd9, 0xe5, 0x18, 0x65, 0x97, 0x9e, 0x35, 0x5b, 0xf3, 0x27, 0x7d, 0xbd, 0x06, 0x13, 0xc7,
0xc2, 0x9b, 0xca, 0x25, 0x27, 0x59, 0x3b, 0x51, 0x3d, 0xa3, 0x7f, 0x6b, 0x97, 0xad, 0x1f, 0xac,
0x95, 0x25, 0x15, 0xea, 0xea, 0x4f, 0x4c, 0x16, 0xbf, 0x3b, 0x9f, 0xb8, 0xba, 0x6d, 0xd6, 0x3f,
0xbf, 0x4f, 0x9c, 0x78, 0x1b, 0xc3, 0xee, 0x1a, 0x66, 0x40, 0xbf, 0xc8, 0xde, 0xe0, 0x5e, 0x5e,
0xa9, 0x7f, 0xfd, 0xbf, 0xd4, 0x96, 0x51, 0xd6, 0x50, 0xc8, 0x4a, 0x94, 0xfb, 0x09, 0x68, 0x25,
0xca, 0xa7, 0x98, 0xc8, 0x06, 0x58, 0x76, 0x34, 0x7a, 0x9c, 0xb1, 0xba, 0xf3, 0x22, 0xeb, 0x87,
0xf7, 0x48, 0xb5, 0xab, 0x97, 0xbf, 0xfa, 0xdd, 0xe9, 0x95, 0x27, 0x26, 0xf3, 0xf7, 0x27, 0xa3,
0x70, 0x7a, 0xea, 0xcb, 0x6d, 0x2e, 0xf0, 0x82, 0xab, 0x80, 0x8b, 0x3f, 0x84, 0xd1, 0xf5, 0xa9,
0x1f, 0x8c, 0x4f, 0xd5, 0xc3, 0x38, 0x5d, 0x78, 0x79, 0xbf, 0xa9, 0xfe, 0xb1, 0xfe, 0xf5, 0x7f,
0x03, 0x00, 0x00, 0xff, 0xff, 0x3e, 0x15, 0x37, 0x36, 0x88, 0x0f, 0x00, 0x00,
// 1931 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x58, 0x4f, 0x73, 0x22, 0xc7,
0x15, 0xf7, 0x08, 0x10, 0xf0, 0x00, 0x69, 0xd4, 0x92, 0xb5, 0xb3, 0x48, 0xf2, 0xca, 0xb3, 0x8e,
0xad, 0xda, 0x5a, 0x4b, 0x1b, 0x52, 0x76, 0x6d, 0xf9, 0x90, 0x14, 0x0b, 0x83, 0x35, 0x5a, 0x18,
0xb4, 0x0d, 0xac, 0xbd, 0xf1, 0xa1, 0xab, 0x05, 0x2d, 0x31, 0xa5, 0x61, 0x06, 0xcf, 0x34, 0x9b,
0x55, 0x0e, 0xa9, 0xca, 0x3d, 0xb9, 0xe6, 0x2b, 0xe4, 0x92, 0x9c, 0xf2, 0x9d, 0x92, 0x4f, 0x90,
0x7b, 0xaa, 0xbb, 0x67, 0x60, 0x40, 0x68, 0x9d, 0x93, 0xe8, 0xdf, 0x7b, 0xfd, 0xfa, 0xf5, 0xfb,
0xf3, 0xeb, 0x37, 0x82, 0xfd, 0x30, 0x98, 0x71, 0x16, 0x86, 0xd3, 0xe1, 0x99, 0xfa, 0x75, 0x3a,
0x0d, 0x03, 0x1e, 0xa0, 0xe2, 0x1c, 0xaf, 0x16, 0xc3, 0xe9, 0x50, 0xa1, 0xe6, 0x9f, 0xb3, 0x80,
0x7a, 0xcc, 0x1f, 0x5d, 0xd2, 0xbb, 0x09, 0xf3, 0x39, 0x66, 0x3f, 0xcf, 0x58, 0xc4, 0x11, 0x82,
0xec, 0x88, 0x45, 0xdc, 0xd0, 0x8e, 0xb5, 0x93, 0x32, 0x96, 0xbf, 0x91, 0x0e, 0x19, 0x3a, 0xe1,
0xc6, 0xc6, 0xb1, 0x76, 0x92, 0xc1, 0xe2, 0x27, 0xfa, 0x1c, 0xca, 0x53, 0xb5, 0x8f, 0x8c, 0x69,
0x34, 0x36, 0x32, 0x52, 0xbb, 0x14, 0x63, 0xe7, 0x34, 0x1a, 0xa3, 0x13, 0xd0, 0xaf, 0x5d, 0x9f,
0x7a, 0x64, 0xe8, 0xf1, 0xf7, 0x64, 0xc4, 0x3c, 0x4e, 0x8d, 0xec, 0xb1, 0x76, 0x92, 0xc3, 0x5b,
0x12, 0x6f, 0x78, 0xfc, 0x7d, 0x53, 0xa0, 0xe8, 0x2b, 0xd8, 0x4e, 0x8c, 0x85, 0xca, 0x0b, 0x23,
0x77, 0xac, 0x9d, 0x14, 0xf1, 0xd6, 0x74, 0xd9, 0xb7, 0xaf, 0x60, 0x9b, 0xbb, 0x13, 0x16, 0xcc,
0x38, 0x89, 0xd8, 0x30, 0xf0, 0x47, 0x91, 0xb1, 0xa9, 0x2c, 0xc6, 0x70, 0x4f, 0xa1, 0xc8, 0x84,
0xca, 0x35, 0x63, 0xc4, 0x73, 0x27, 0x2e, 0x27, 0x11, 0xe5, 0x46, 0x5e, 0xba, 0x5e, 0xba, 0x66,
0xac, 0x2d, 0xb0, 0x1e, 0xe5, 0xe8, 0x39, 0xe8, 0xc1, 0x8c, 0xdf, 0x04, 0xae, 0x7f, 0x43, 0x86,
0x63, 0xea, 0x13, 0x77, 0x64, 0x14, 0x8e, 0xb5, 0x93, 0xec, 0xab, 0x8d, 0x17, 0x1a, 0xde, 0x4a,
0x64, 0x8d, 0x31, 0xf5, 0xed, 0x11, 0x3a, 0x02, 0x90, 0xf7, 0x90, 0x26, 0x8d, 0xa2, 0x3c, 0xb5,
0x28, 0x10, 0x69, 0x0f, 0xd5, 0xa0, 0x24, 0x83, 0x4c, 0xc6, 0xae, 0xcf, 0x23, 0x03, 0x8e, 0x33,
0x27, 0xa5, 0x9a, 0x7e, 0xea, 0xf9, 0x22, 0xde, 0x58, 0x48, 0xce, 0x5d, 0x9f, 0xe3, 0xb4, 0x12,
0xb2, 0xa0, 0x20, 0xa2, 0x4b, 0xb8, 0xf7, 0xde, 0x28, 0xc9, 0x0d, 0xcf, 0x4e, 0xe7, 0x99, 0x3a,
0xbd, 0x9f, 0x9a, 0xd3, 0x26, 0x8b, 0x78, 0xdf, 0x7b, 0x6f, 0xf9, 0x3c, 0xbc, 0xc3, 0xf9, 0x91,
0x5a, 0x55, 0xbf, 0x83, 0x72, 0x5a, 0x20, 0x92, 0x75, 0xcb, 0xee, 0x64, 0xfe, 0xb2, 0x58, 0xfc,
0x44, 0x7b, 0x90, 0x7b, 0x4f, 0xbd, 0x19, 0x93, 0x09, 0x2c, 0x63, 0xb5, 0xf8, 0x6e, 0xe3, 0xa5,
0x66, 0xbe, 0x84, 0xdd, 0x7e, 0x48, 0x87, 0xb7, 0x2b, 0x35, 0xb0, 0x9a, 0x5d, 0xed, 0x5e, 0x76,
0xcd, 0x3f, 0x41, 0x25, 0xde, 0xd4, 0xe3, 0x94, 0xcf, 0x22, 0xf4, 0x35, 0xe4, 0x22, 0x4e, 0x39,
0x93, 0xca, 0x5b, 0xb5, 0x47, 0xa9, 0xab, 0xa4, 0x14, 0x19, 0x56, 0x5a, 0xa8, 0x0a, 0x85, 0x69,
0xc8, 0xdc, 0x09, 0xbd, 0x49, 0xdc, 0x9a, 0xaf, 0x91, 0x09, 0x39, 0xb9, 0x59, 0x56, 0x55, 0xa9,
0x56, 0x4e, 0x87, 0x11, 0x2b, 0x91, 0xf9, 0x5b, 0xd8, 0x96, 0xeb, 0x16, 0x63, 0x1f, 0xab, 0xdc,
0x47, 0x90, 0xa7, 0x13, 0x55, 0x02, 0xaa, 0x7a, 0x37, 0xe9, 0x44, 0x64, 0xdf, 0x1c, 0x81, 0xbe,
0xd8, 0x1f, 0x4d, 0x03, 0x3f, 0x62, 0xa2, 0x62, 0x85, 0x71, 0x51, 0x10, 0xa2, 0x7a, 0x26, 0x62,
0x97, 0x26, 0x77, 0x6d, 0xc5, 0x78, 0x8b, 0xb1, 0x4e, 0x44, 0x39, 0xfa, 0x52, 0x15, 0x22, 0xf1,
0x82, 0xe1, 0xad, 0x28, 0x6d, 0x7a, 0x17, 0x9b, 0xaf, 0x08, 0xb8, 0x1d, 0x0c, 0x6f, 0x9b, 0x02,
0x34, 0x7f, 0x52, 0x2d, 0xd6, 0x0f, 0x94, 0xef, 0xff, 0x77, 0x78, 0x17, 0x21, 0xd8, 0x78, 0x38,
0x04, 0x04, 0x76, 0x97, 0x8c, 0xc7, 0xb7, 0x48, 0x47, 0x56, 0x5b, 0x89, 0xec, 0x73, 0xc8, 0x5f,
0x53, 0xd7, 0x9b, 0x85, 0x89, 0x61, 0x94, 0x4a, 0x53, 0x4b, 0x49, 0x70, 0xa2, 0x62, 0xfe, 0x37,
0x0f, 0xf9, 0x18, 0x44, 0x35, 0xc8, 0x0e, 0x83, 0x51, 0x92, 0xdd, 0xcf, 0xee, 0x6f, 0x4b, 0xfe,
0x36, 0x82, 0x11, 0xc3, 0x52, 0x17, 0xfd, 0x0e, 0xb6, 0x44, 0x63, 0xf9, 0xcc, 0x23, 0xb3, 0xe9,
0x88, 0xce, 0x13, 0x6a, 0xa4, 0x76, 0x37, 0x94, 0xc2, 0x40, 0xca, 0x71, 0x65, 0x98, 0x5e, 0xa2,
0x03, 0x28, 0x8e, 0xb9, 0x37, 0x54, 0x99, 0xc8, 0xca, 0x82, 0x2e, 0x08, 0x40, 0xe6, 0xc0, 0x84,
0x4a, 0xe0, 0xbb, 0x81, 0x4f, 0xa2, 0x31, 0x25, 0xb5, 0x6f, 0xbe, 0x95, 0x9c, 0x51, 0xc6, 0x25,
0x09, 0xf6, 0xc6, 0xb4, 0xf6, 0xcd, 0xb7, 0xe8, 0x09, 0x94, 0x64, 0xd7, 0xb2, 0x0f, 0x53, 0x37,
0xbc, 0x93, 0x64, 0x51, 0xc1, 0xb2, 0x91, 0x2d, 0x89, 0x88, 0xd6, 0xb8, 0xf6, 0xe8, 0x4d, 0x24,
0x09, 0xa2, 0x82, 0xd5, 0x02, 0xbd, 0x80, 0xbd, 0x38, 0x06, 0x24, 0x0a, 0x66, 0xe1, 0x90, 0x11,
0xd7, 0x1f, 0xb1, 0x0f, 0x92, 0x1e, 0x2a, 0x18, 0xc5, 0xb2, 0x9e, 0x14, 0xd9, 0x42, 0x82, 0xf6,
0x61, 0x73, 0xcc, 0xdc, 0x9b, 0xb1, 0xa2, 0x86, 0x0a, 0x8e, 0x57, 0xe6, 0x3f, 0x72, 0x50, 0x4a,
0x05, 0x06, 0x95, 0xa1, 0x80, 0xad, 0x9e, 0x85, 0xdf, 0x5a, 0x4d, 0xfd, 0x13, 0x74, 0x02, 0x5f,
0xd8, 0x4e, 0xa3, 0x8b, 0xb1, 0xd5, 0xe8, 0x93, 0x2e, 0x26, 0x03, 0xe7, 0xb5, 0xd3, 0xfd, 0xc1,
0x21, 0x97, 0xf5, 0x77, 0x1d, 0xcb, 0xe9, 0x93, 0xa6, 0xd5, 0xaf, 0xdb, 0xed, 0x9e, 0xae, 0xa1,
0x43, 0x30, 0x16, 0x9a, 0x89, 0xb8, 0xde, 0xe9, 0x0e, 0x9c, 0xbe, 0xbe, 0x81, 0x9e, 0xc0, 0x41,
0xcb, 0x76, 0xea, 0x6d, 0xb2, 0xd0, 0x69, 0xb4, 0xfb, 0x6f, 0x89, 0xf5, 0xe3, 0xa5, 0x8d, 0xdf,
0xe9, 0x99, 0x75, 0x0a, 0xe7, 0xfd, 0x76, 0x23, 0xb1, 0x90, 0x45, 0x8f, 0xe1, 0x53, 0xa5, 0xa0,
0xb6, 0x90, 0x7e, 0xb7, 0x4b, 0x7a, 0xdd, 0xae, 0xa3, 0xe7, 0xd0, 0x0e, 0x54, 0x6c, 0xe7, 0x6d,
0xbd, 0x6d, 0x37, 0x09, 0xb6, 0xea, 0xed, 0x8e, 0xbe, 0x89, 0x76, 0x61, 0x7b, 0x55, 0x2f, 0x2f,
0x4c, 0x24, 0x7a, 0x5d, 0xc7, 0xee, 0x3a, 0xe4, 0xad, 0x85, 0x7b, 0x76, 0xd7, 0xd1, 0x0b, 0x68,
0x1f, 0xd0, 0xb2, 0xe8, 0xbc, 0x53, 0x6f, 0xe8, 0x45, 0xf4, 0x29, 0xec, 0x2c, 0xe3, 0xaf, 0xad,
0x77, 0x3a, 0x20, 0x03, 0xf6, 0x94, 0x63, 0xe4, 0x95, 0xd5, 0xee, 0xfe, 0x40, 0x3a, 0xb6, 0x63,
0x77, 0x06, 0x1d, 0xbd, 0x84, 0xf6, 0x40, 0x6f, 0x59, 0x16, 0xb1, 0x9d, 0xde, 0xa0, 0xd5, 0xb2,
0x1b, 0xb6, 0xe5, 0xf4, 0xf5, 0xb2, 0x3a, 0x79, 0xdd, 0xc5, 0x2b, 0x62, 0x43, 0xe3, 0xbc, 0xee,
0x38, 0x56, 0x9b, 0x34, 0xed, 0x5e, 0xfd, 0x55, 0xdb, 0x6a, 0xea, 0x5b, 0xe8, 0x08, 0x1e, 0xf7,
0xad, 0xce, 0x65, 0x17, 0xd7, 0xf1, 0x3b, 0x92, 0xc8, 0x5b, 0x75, 0xbb, 0x3d, 0xc0, 0x96, 0xbe,
0x8d, 0x3e, 0x87, 0x23, 0x6c, 0xbd, 0x19, 0xd8, 0xd8, 0x6a, 0x12, 0xa7, 0xdb, 0xb4, 0x48, 0xcb,
0xaa, 0xf7, 0x07, 0xd8, 0x22, 0x1d, 0xbb, 0xd7, 0xb3, 0x9d, 0xef, 0x75, 0x1d, 0x7d, 0x01, 0xc7,
0x73, 0x95, 0xb9, 0x81, 0x15, 0xad, 0x1d, 0x71, 0xbf, 0x24, 0xa5, 0x8e, 0xf5, 0x63, 0x9f, 0x5c,
0x5a, 0x16, 0xd6, 0x11, 0xaa, 0xc2, 0xfe, 0xe2, 0x78, 0x75, 0x40, 0x7c, 0xf6, 0xae, 0x90, 0x5d,
0x5a, 0xb8, 0x53, 0x77, 0x44, 0x82, 0x97, 0x64, 0x7b, 0xc2, 0xed, 0x85, 0x6c, 0xd5, 0xed, 0x4f,
0x11, 0x82, 0xad, 0x54, 0x56, 0x5a, 0x75, 0xac, 0xef, 0xa3, 0x3d, 0xd8, 0x4e, 0x3c, 0x48, 0x14,
0xff, 0x9d, 0x47, 0x8f, 0x00, 0x0d, 0x1c, 0x6c, 0xd5, 0x9b, 0x22, 0x20, 0x73, 0xc1, 0x7f, 0xf2,
0x17, 0xd9, 0xc2, 0x86, 0x9e, 0x31, 0xff, 0x95, 0x81, 0xca, 0x52, 0x5f, 0xa2, 0x43, 0x28, 0x46,
0xee, 0x8d, 0x4f, 0xb9, 0x60, 0x0e, 0x45, 0x2a, 0x0b, 0x40, 0xbe, 0x8d, 0x63, 0xea, 0xfa, 0x8a,
0xcd, 0x14, 0x9b, 0x17, 0x25, 0x22, 0xb9, 0xec, 0x00, 0xf2, 0xc9, 0xfb, 0x9a, 0x99, 0xbf, 0xaf,
0x9b, 0x43, 0xf5, 0xae, 0x1e, 0x42, 0x51, 0x50, 0x66, 0xc4, 0xe9, 0x64, 0x2a, 0x5b, 0xbc, 0x82,
0x17, 0x00, 0x7a, 0x0a, 0x95, 0x09, 0x8b, 0x22, 0x7a, 0xc3, 0x88, 0x6a, 0x53, 0x90, 0x1a, 0xe5,
0x18, 0x6c, 0xc9, 0x6e, 0x7d, 0x0a, 0x09, 0x6d, 0xc4, 0x4a, 0x39, 0xa5, 0x14, 0x83, 0x4a, 0x69,
0x95, 0xb1, 0x39, 0x8d, 0xd9, 0x20, 0xcd, 0xd8, 0x9c, 0xa2, 0x67, 0xb0, 0xa3, 0x28, 0xc7, 0xf5,
0xdd, 0xc9, 0x6c, 0xa2, 0xa8, 0x27, 0x2f, 0xa9, 0x67, 0x5b, 0x52, 0x8f, 0xc2, 0x25, 0x03, 0x3d,
0x86, 0xc2, 0x15, 0x8d, 0x98, 0x78, 0x2c, 0x62, 0x6a, 0xc8, 0x8b, 0x75, 0x8b, 0x31, 0x21, 0x12,
0x4f, 0x48, 0x28, 0x48, 0x4f, 0x31, 0x42, 0xfe, 0x9a, 0x31, 0x2c, 0x62, 0x39, 0x3f, 0x81, 0x7e,
0x58, 0x9c, 0x50, 0x4a, 0x9d, 0xa0, 0x70, 0x79, 0xc2, 0x33, 0xd8, 0x61, 0x1f, 0x78, 0x48, 0x49,
0x30, 0xa5, 0x3f, 0xcf, 0x18, 0x19, 0x51, 0x4e, 0x8d, 0xb2, 0x0c, 0xf0, 0xb6, 0x14, 0x74, 0x25,
0xde, 0xa4, 0x9c, 0x9a, 0x87, 0x50, 0xc5, 0x2c, 0x62, 0xbc, 0xe3, 0x46, 0x91, 0x1b, 0xf8, 0x8d,
0xc0, 0xe7, 0x61, 0xe0, 0xc5, 0x6f, 0x8e, 0x79, 0x04, 0x07, 0x6b, 0xa5, 0xea, 0xd1, 0x10, 0x9b,
0xdf, 0xcc, 0x58, 0x78, 0xb7, 0x7e, 0xf3, 0x1b, 0x38, 0x58, 0x2b, 0x8d, 0x5f, 0x9c, 0xe7, 0x90,
0x9b, 0x52, 0x37, 0x8c, 0x8c, 0x0d, 0x39, 0xc5, 0xec, 0x2f, 0x3d, 0xfd, 0x6e, 0x78, 0xee, 0x46,
0x3c, 0x08, 0xef, 0xb0, 0x52, 0xba, 0xc8, 0x16, 0x34, 0x7d, 0xc3, 0xfc, 0x8b, 0x06, 0xa5, 0x94,
0x50, 0xd4, 0x81, 0x1f, 0x8c, 0x18, 0xb9, 0x0e, 0x83, 0x49, 0x52, 0x61, 0x73, 0x00, 0x19, 0x90,
0x97, 0x0b, 0x1e, 0xc4, 0xe5, 0x95, 0x2c, 0xd1, 0xd7, 0x90, 0x1f, 0x2b, 0x13, 0x32, 0x4b, 0xa5,
0xda, 0xee, 0xca, 0xe9, 0x22, 0x36, 0x38, 0xd1, 0xb9, 0xc8, 0x16, 0x32, 0x7a, 0xf6, 0x22, 0x5b,
0xc8, 0xea, 0xb9, 0x8b, 0x6c, 0x21, 0xa7, 0x6f, 0x5e, 0x64, 0x0b, 0x9b, 0x7a, 0xde, 0xfc, 0x9b,
0x06, 0x85, 0x44, 0x7b, 0xb9, 0x26, 0xd5, 0x00, 0x90, 0xaa, 0xc9, 0x1a, 0xec, 0x4d, 0x5c, 0x9f,
0x4c, 0x99, 0x4f, 0x3d, 0xf7, 0x8f, 0x8c, 0x2c, 0xcf, 0x17, 0x6b, 0x65, 0xe8, 0x25, 0x3c, 0xf2,
0x68, 0xc4, 0x09, 0xe5, 0x9c, 0x4d, 0xa6, 0x9c, 0x44, 0xb3, 0xe1, 0x90, 0x45, 0xd1, 0xf5, 0xcc,
0x93, 0x2d, 0x51, 0xc0, 0x0f, 0x89, 0xcd, 0x09, 0x3c, 0x92, 0xa1, 0xbf, 0x0c, 0x83, 0x2b, 0x7a,
0xe5, 0x7a, 0x2e, 0xbf, 0x4b, 0xc6, 0x88, 0x43, 0x28, 0x8a, 0xe0, 0x10, 0x3f, 0x79, 0x97, 0xcb,
0x78, 0x01, 0x88, 0x90, 0xf1, 0x40, 0xc9, 0xe2, 0x90, 0xc5, 0x4b, 0x31, 0x20, 0x08, 0xbf, 0x64,
0xdd, 0x65, 0xa4, 0xd3, 0xf3, 0xb5, 0x79, 0x0b, 0xc6, 0xfd, 0xe3, 0xe2, 0x34, 0x1f, 0x43, 0x69,
0xba, 0x80, 0xe5, 0x89, 0x1a, 0x4e, 0x43, 0xe9, 0x64, 0x6c, 0xfc, 0x72, 0x32, 0xcc, 0xbf, 0x6b,
0xb0, 0xf3, 0x6a, 0xe6, 0x7a, 0xa3, 0xa5, 0xe9, 0xe8, 0x71, 0xca, 0x3d, 0x15, 0x7c, 0x31, 0xc2,
0xc9, 0x76, 0x58, 0xf7, 0x49, 0xb1, 0xb1, 0xf6, 0x93, 0x62, 0xdd, 0x70, 0x9f, 0x79, 0x70, 0xb8,
0x7f, 0x02, 0xa5, 0x71, 0x30, 0x25, 0xd3, 0xd9, 0xd5, 0x2d, 0xbb, 0x8b, 0x8c, 0xec, 0x71, 0xe6,
0xa4, 0x8c, 0x61, 0x1c, 0x4c, 0x2f, 0x15, 0x62, 0xbe, 0x04, 0x94, 0x76, 0x34, 0x0e, 0xc8, 0x7c,
0x48, 0xd3, 0x1e, 0x1c, 0xd2, 0x9e, 0xfd, 0x55, 0x83, 0x72, 0x7a, 0xfe, 0x45, 0x15, 0x28, 0xda,
0x0e, 0x69, 0xb5, 0xed, 0xef, 0xcf, 0xfb, 0xfa, 0x27, 0x62, 0xd9, 0x1b, 0x34, 0x1a, 0x96, 0xd5,
0xb4, 0x9a, 0xba, 0x26, 0x38, 0x5c, 0xd0, 0xb1, 0xd5, 0x24, 0x7d, 0xbb, 0x63, 0x75, 0x07, 0xe2,
0x75, 0xdf, 0x85, 0xed, 0x18, 0x73, 0xba, 0x04, 0x77, 0x07, 0x7d, 0x4b, 0xcf, 0x20, 0x1d, 0xca,
0x31, 0x68, 0x61, 0xdc, 0xc5, 0x7a, 0x56, 0x3c, 0x49, 0x31, 0x72, 0x7f, 0x52, 0x48, 0x06, 0x89,
0x5c, 0xed, 0x9f, 0x39, 0xd8, 0x94, 0x0e, 0x86, 0xe8, 0x1c, 0x4a, 0xa9, 0x8f, 0x0c, 0x74, 0xf4,
0xd1, 0x8f, 0x8f, 0xaa, 0xb1, 0x7e, 0xa0, 0x9f, 0x45, 0x2f, 0x34, 0x74, 0x01, 0xe5, 0xf4, 0x67,
0x04, 0x4a, 0x8f, 0x87, 0x6b, 0xbe, 0x2f, 0x3e, 0x6a, 0xeb, 0x35, 0xe8, 0x56, 0xc4, 0xdd, 0x89,
0x18, 0x07, 0xe3, 0x01, 0x1d, 0x55, 0x53, 0xfa, 0x2b, 0x53, 0x7f, 0xf5, 0x60, 0xad, 0x2c, 0xce,
0x50, 0x5b, 0x5d, 0x31, 0x1e, 0x91, 0xef, 0x5d, 0x71, 0x79, 0x2e, 0xaf, 0x7e, 0xf6, 0x90, 0x38,
0xb6, 0x36, 0x82, 0xdd, 0x35, 0x1c, 0x8a, 0x7e, 0x95, 0xf6, 0xe0, 0x41, 0x06, 0xae, 0x7e, 0xf9,
0x4b, 0x6a, 0x8b, 0x53, 0xd6, 0x90, 0xed, 0xd2, 0x29, 0x0f, 0x53, 0xf5, 0xd2, 0x29, 0x1f, 0xe3,
0xec, 0x9f, 0x40, 0x5f, 0x6d, 0x74, 0x64, 0xae, 0xee, 0xbd, 0x4f, 0x3a, 0xd5, 0xa7, 0x1f, 0xd5,
0x89, 0x8d, 0xdb, 0x00, 0x8b, 0x76, 0x41, 0x87, 0xa9, 0x2d, 0xf7, 0xda, 0xbd, 0x7a, 0xf4, 0x80,
0x54, 0x99, 0x7a, 0xf5, 0xeb, 0xdf, 0x9f, 0xdd, 0xb8, 0x7c, 0x3c, 0xbb, 0x3a, 0x1d, 0x06, 0x93,
0x33, 0x4f, 0x0c, 0xd5, 0xbe, 0xeb, 0xdf, 0xf8, 0x8c, 0xff, 0x21, 0x08, 0x6f, 0xcf, 0x3c, 0x7f,
0x74, 0x26, 0xbb, 0xee, 0x6c, 0x6e, 0xe5, 0x6a, 0x53, 0xfe, 0x7f, 0xe3, 0x37, 0xff, 0x0b, 0x00,
0x00, 0xff, 0xff, 0x1d, 0x08, 0x9a, 0xb8, 0x0f, 0x11, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@ -1418,6 +1575,10 @@ type RouterClient interface {
//It is a development feature.
QueryMissionControl(ctx context.Context, in *QueryMissionControlRequest, opts ...grpc.CallOption) (*QueryMissionControlResponse, error)
//*
//QueryProbability returns the current success probability estimate for a
//given node pair and amount.
QueryProbability(ctx context.Context, in *QueryProbabilityRequest, opts ...grpc.CallOption) (*QueryProbabilityResponse, error)
//*
//BuildRoute builds a fully specified route based on a list of hop public
//keys. It retrieves the relevant channel policies from the graph in order to
//calculate the correct fees and time locks.
@ -1532,6 +1693,15 @@ func (c *routerClient) QueryMissionControl(ctx context.Context, in *QueryMission
return out, nil
}
func (c *routerClient) QueryProbability(ctx context.Context, in *QueryProbabilityRequest, opts ...grpc.CallOption) (*QueryProbabilityResponse, error) {
out := new(QueryProbabilityResponse)
err := c.cc.Invoke(ctx, "/routerrpc.Router/QueryProbability", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *routerClient) BuildRoute(ctx context.Context, in *BuildRouteRequest, opts ...grpc.CallOption) (*BuildRouteResponse, error) {
out := new(BuildRouteResponse)
err := c.cc.Invoke(ctx, "/routerrpc.Router/BuildRoute", in, out, opts...)
@ -1570,6 +1740,10 @@ type RouterServer interface {
//It is a development feature.
QueryMissionControl(context.Context, *QueryMissionControlRequest) (*QueryMissionControlResponse, error)
//*
//QueryProbability returns the current success probability estimate for a
//given node pair and amount.
QueryProbability(context.Context, *QueryProbabilityRequest) (*QueryProbabilityResponse, error)
//*
//BuildRoute builds a fully specified route based on a list of hop public
//keys. It retrieves the relevant channel policies from the graph in order to
//calculate the correct fees and time locks.
@ -1694,6 +1868,24 @@ func _Router_QueryMissionControl_Handler(srv interface{}, ctx context.Context, d
return interceptor(ctx, in, info, handler)
}
func _Router_QueryProbability_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(QueryProbabilityRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RouterServer).QueryProbability(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/routerrpc.Router/QueryProbability",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RouterServer).QueryProbability(ctx, req.(*QueryProbabilityRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Router_BuildRoute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(BuildRouteRequest)
if err := dec(in); err != nil {
@ -1732,6 +1924,10 @@ var _Router_serviceDesc = grpc.ServiceDesc{
MethodName: "QueryMissionControl",
Handler: _Router_QueryMissionControl_Handler,
},
{
MethodName: "QueryProbability",
Handler: _Router_QueryProbability_Handler,
},
{
MethodName: "BuildRoute",
Handler: _Router_BuildRoute_Handler,

@ -351,16 +351,39 @@ message PairHistory {
/// The destination node pubkey of the pair.
bytes node_to = 2 [json_name="node_to"];
reserved 3, 4, 5, 6;
PairData history = 7 [json_name="history"];
}
message PairData {
/// Time stamp of last result.
int64 timestamp = 3 [json_name = "timestamp"];
int64 timestamp = 1 [json_name = "timestamp"];
/// Minimum penalization amount (only applies to failed attempts).
int64 min_penalize_amt_sat = 4 [json_name = "min_penalize_amt_sat"];
reserved 5;
int64 min_penalize_amt_sat = 2 [json_name = "min_penalize_amt_sat"];
/// Whether the last payment attempt through this pair was successful.
bool last_attempt_successful = 6 [json_name = "last_attempt_successful"];
bool last_attempt_successful = 3 [json_name = "last_attempt_successful"];
}
message QueryProbabilityRequest{
/// The source node pubkey of the pair.
bytes from_node = 1 [json_name = "from_node"];
/// The destination node pubkey of the pair.
bytes to_node = 2 [json_name = "to_node"];
/// The amount for which to calculate a probability.
int64 amt_msat = 3 [json_name = "amt_msat"];
}
message QueryProbabilityResponse{
/// The success probability for the requested pair.
double probability = 1 [json_name = "probability"];
/// The historical data for the requested pair.
PairData history = 2 [json_name = "history"];
}
message BuildRouteRequest {
@ -436,6 +459,12 @@ service Router {
*/
rpc QueryMissionControl(QueryMissionControlRequest) returns (QueryMissionControlResponse);
/**
QueryProbability returns the current success probability estimate for a
given node pair and amount.
*/
rpc QueryProbability(QueryProbabilityRequest) returns (QueryProbabilityResponse);
/**
BuildRoute builds a fully specified route based on a list of hop public
keys. It retrieves the relevant channel policies from the graph in order to

@ -76,6 +76,11 @@ type MissionControl interface {
// GetHistorySnapshot takes a snapshot from the current mission control
// state and actual probability estimates.
GetHistorySnapshot() *routing.MissionControlSnapshot
// GetPairHistorySnapshot returns the stored history for a given node
// pair.
GetPairHistorySnapshot(fromNode,
toNode route.Vertex) routing.TimedPairResult
}
// QueryRoutes attempts to query the daemons' Channel Router for a possible

@ -174,3 +174,9 @@ func (m *mockMissionControl) ResetHistory() error {
func (m *mockMissionControl) GetHistorySnapshot() *routing.MissionControlSnapshot {
return nil
}
func (m *mockMissionControl) GetPairHistorySnapshot(fromNode,
toNode route.Vertex) routing.TimedPairResult {
return routing.TimedPairResult{}
}

@ -68,6 +68,10 @@ var (
Entity: "offchain",
Action: "read",
}},
"/routerrpc.Router/QueryProbability": {{
Entity: "offchain",
Action: "read",
}},
"/routerrpc.Router/ResetMissionControl": {{
Entity: "offchain",
Action: "write",
@ -474,11 +478,7 @@ func (s *Server) QueryMissionControl(ctx context.Context,
rpcPair := PairHistory{
NodeFrom: pair.Pair.From[:],
NodeTo: pair.Pair.To[:],
Timestamp: pair.Timestamp.Unix(),
MinPenalizeAmtSat: int64(
pair.MinPenalizeAmt.ToSatoshis(),
),
LastAttemptSuccessful: pair.LastAttemptSuccessful,
History: toRPCPairData(&pair.TimedPairResult),
}
rpcPairs = append(rpcPairs, &rpcPair)
@ -491,6 +491,49 @@ func (s *Server) QueryMissionControl(ctx context.Context,
return &response, nil
}
// toRPCPairData marshalls mission control pair data to the rpc struct.
func toRPCPairData(data *routing.TimedPairResult) *PairData {
rpcData := PairData{
MinPenalizeAmtSat: int64(
data.MinPenalizeAmt.ToSatoshis(),
),
LastAttemptSuccessful: data.Success,
}
if !data.Timestamp.IsZero() {
rpcData.Timestamp = data.Timestamp.Unix()
}
return &rpcData
}
// QueryProbability returns the current success probability estimate for a
// given node pair and amount.
func (s *Server) QueryProbability(ctx context.Context,
req *QueryProbabilityRequest) (*QueryProbabilityResponse, error) {
fromNode, err := route.NewVertexFromBytes(req.FromNode)
if err != nil {
return nil, err
}
toNode, err := route.NewVertexFromBytes(req.ToNode)
if err != nil {
return nil, err
}
amt := lnwire.MilliSatoshi(req.AmtMsat)
mc := s.cfg.RouterBackend.MissionControl
prob := mc.GetProbability(fromNode, toNode, amt)
history := mc.GetPairHistorySnapshot(fromNode, toNode)
return &QueryProbabilityResponse{
Probability: prob,
History: toRPCPairData(&history),
}, nil
}
// TrackPayment returns a stream of payment state updates. The stream is
// closed when the payment completes.
func (s *Server) TrackPayment(request *TrackPaymentRequest,

@ -53,7 +53,7 @@ const (
)
// NodeResults contains previous results from a node to its peers.
type NodeResults map[route.Vertex]timedPairResult
type NodeResults map[route.Vertex]TimedPairResult
// MissionControl contains state which summarizes the past attempts of HTLC
// routing by external callers when sending payments throughout the network. It
@ -120,12 +120,29 @@ type MissionControlConfig struct {
AprioriWeight float64
}
// timedPairResult describes a timestamped pair result.
type timedPairResult struct {
// TimedPairResult describes a timestamped pair result.
type TimedPairResult struct {
// timestamp is the time when this result was obtained.
timestamp time.Time
Timestamp time.Time
pairResult
// minPenalizeAmt is the minimum amount for which a penalty should be
// applied based on this result. Only applies to fail results.
MinPenalizeAmt lnwire.MilliSatoshi
// success indicates whether the payment attempt was successful through
// this pair.
Success bool
}
// newTimedPairResult wraps a pair result with a timestamp.
func newTimedPairResult(timestamp time.Time,
result pairResult) TimedPairResult {
return TimedPairResult{
Timestamp: timestamp,
MinPenalizeAmt: result.minPenalizeAmt,
Success: result.success,
}
}
// MissionControlSnapshot contains a snapshot of the current state of mission
@ -142,16 +159,8 @@ type MissionControlPairSnapshot struct {
// Pair is the node pair of which the state is described.
Pair DirectedNodePair
// Timestamp is the time of last result.
Timestamp time.Time
// MinPenalizeAmt is the minimum amount for which the channel will be
// penalized.
MinPenalizeAmt lnwire.MilliSatoshi
// LastAttemptSuccessful indicates whether the last payment attempt
// through this pair was successful.
LastAttemptSuccessful bool
// TimedPairResult contains the data for this pair.
TimedPairResult
}
// paymentResult is the information that becomes available when a payment
@ -257,7 +266,7 @@ func (m *MissionControl) GetProbability(fromNode, toNode route.Vertex,
// setLastPairResult stores a result for a node pair.
func (m *MissionControl) setLastPairResult(fromNode,
toNode route.Vertex, result timedPairResult) {
toNode route.Vertex, result TimedPairResult) {
nodePairs, ok := m.lastPairResult[fromNode]
if !ok {
@ -278,10 +287,9 @@ func (m *MissionControl) setAllFail(fromNode route.Vertex,
}
for connection := range nodePairs {
nodePairs[connection] = timedPairResult{
timestamp: timestamp,
pairResult: failPairResult(0),
}
nodePairs[connection] = newTimedPairResult(
timestamp, failPairResult(0),
)
}
}
@ -329,14 +337,11 @@ func (m *MissionControl) GetHistorySnapshot() *MissionControlSnapshot {
for fromNode, fromPairs := range m.lastPairResult {
for toNode, result := range fromPairs {
pair := NewDirectedNodePair(fromNode, toNode)
pairSnapshot := MissionControlPairSnapshot{
Pair: pair,
MinPenalizeAmt: result.minPenalizeAmt,
Timestamp: result.timestamp,
LastAttemptSuccessful: result.success,
TimedPairResult: result,
}
pairs = append(pairs, pairSnapshot)
@ -350,6 +355,26 @@ func (m *MissionControl) GetHistorySnapshot() *MissionControlSnapshot {
return &snapshot
}
// GetPairHistorySnapshot returns the stored history for a given node pair.
func (m *MissionControl) GetPairHistorySnapshot(
fromNode, toNode route.Vertex) TimedPairResult {
m.Lock()
defer m.Unlock()
results, ok := m.lastPairResult[fromNode]
if !ok {
return TimedPairResult{}
}
result, ok := results[toNode]
if !ok {
return TimedPairResult{}
}
return result
}
// ReportPaymentFail reports a failed payment to mission control as input for
// future probability estimates. The failureSourceIdx argument indicates the
// failure source. If it is nil, the failure source is unknown. This function
@ -468,10 +493,13 @@ func (m *MissionControl) applyPaymentResult(
pair, pairResult.minPenalizeAmt)
}
m.setLastPairResult(pair.From, pair.To, timedPairResult{
timestamp: result.timeReply,
pairResult: pairResult,
})
m.setLastPairResult(
pair.From, pair.To,
newTimedPairResult(
result.timeReply,
pairResult,
),
)
}
return i.finalFailureReason

@ -80,19 +80,19 @@ func (p *probabilityEstimator) getNodeProbability(now time.Time,
totalWeight := aprioriFactor
for _, result := range results {
age := now.Sub(result.timestamp)
age := now.Sub(result.Timestamp)
switch {
// Weigh success with a constant high weight of 1. There is no
// decay.
case result.success:
case result.Success:
totalWeight++
probabilitiesTotal += p.prevSuccessProbability
// Weigh failures in accordance with their age. The base
// probability of a failure is considered zero, so nothing needs
// to be added to probabilitiesTotal.
case amt >= result.minPenalizeAmt:
case amt >= result.MinPenalizeAmt:
totalWeight += p.getWeight(age)
}
}
@ -127,7 +127,7 @@ func (p *probabilityEstimator) getPairProbability(
// For successes, we have a fixed (high) probability. Those pairs
// will be assumed good until proven otherwise.
if lastPairResult.success {
if lastPairResult.Success {
return p.prevSuccessProbability
}
@ -138,11 +138,11 @@ func (p *probabilityEstimator) getPairProbability(
// penalization. If the current amount is smaller than the amount that
// previously triggered a failure, we act as if this is an untried
// channel.
if amt < lastPairResult.minPenalizeAmt {
if amt < lastPairResult.MinPenalizeAmt {
return nodeProbability
}
timeSinceLastFailure := now.Sub(lastPairResult.timestamp)
timeSinceLastFailure := now.Sub(lastPairResult.Timestamp)
// Calculate success probability based on the weight of the last
// failure. When the failure is fresh, its weight is 1 and we'll return

@ -33,7 +33,7 @@ type estimatorTestContext struct {
// corresponds to the last result towards a node. The list index equals
// the node id. So the first element in the list is the result towards
// node 0.
results map[int]timedPairResult
results map[int]TimedPairResult
}
func newEstimatorTestContext(t *testing.T) *estimatorTestContext {
@ -83,11 +83,11 @@ func TestProbabilityEstimatorNoResults(t *testing.T) {
func TestProbabilityEstimatorOneSuccess(t *testing.T) {
ctx := newEstimatorTestContext(t)
ctx.results = map[int]timedPairResult{
node1: {
timestamp: testTime.Add(-time.Hour),
pairResult: successPairResult(),
},
ctx.results = map[int]TimedPairResult{
node1: newTimedPairResult(
testTime.Add(-time.Hour),
successPairResult(),
),
}
// Because of the previous success, this channel keep reporting a high
@ -107,11 +107,11 @@ func TestProbabilityEstimatorOneSuccess(t *testing.T) {
func TestProbabilityEstimatorOneFailure(t *testing.T) {
ctx := newEstimatorTestContext(t)
ctx.results = map[int]timedPairResult{
node1: {
timestamp: testTime.Add(-time.Hour),
pairResult: failPairResult(0),
},
ctx.results = map[int]TimedPairResult{
node1: newTimedPairResult(
testTime.Add(-time.Hour),
failPairResult(0),
),
}
// For an untried node, we expected the node probability. The weight for
@ -130,19 +130,19 @@ func TestProbabilityEstimatorOneFailure(t *testing.T) {
func TestProbabilityEstimatorMix(t *testing.T) {
ctx := newEstimatorTestContext(t)
ctx.results = map[int]timedPairResult{
node1: {
timestamp: testTime.Add(-time.Hour),
pairResult: successPairResult(),
},
node2: {
timestamp: testTime.Add(-2 * time.Hour),
pairResult: failPairResult(0),
},
node3: {
timestamp: testTime.Add(-3 * time.Hour),
pairResult: failPairResult(0),
},
ctx.results = map[int]TimedPairResult{
node1: newTimedPairResult(
testTime.Add(-time.Hour),
successPairResult(),
),
node2: newTimedPairResult(
testTime.Add(-2*time.Hour),
failPairResult(0),
),
node3: newTimedPairResult(
testTime.Add(-3*time.Hour),
failPairResult(0),
),
}
// We expect the probability for a previously successful channel to