Merge pull request #2794 from halseth/autopilot-query-heuristic-no-active-agent

autopilot: move queryHeuristic out of agent
This commit is contained in:
Olaoluwa Osuntokun 2019-03-21 20:20:51 -07:00 committed by GitHub
commit 6440f39120
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 145 additions and 104 deletions

@ -819,55 +819,3 @@ func (a *Agent) executeDirective(directive AttachmentDirective) {
// directive in goroutine? // directive in goroutine?
a.OnChannelPendingOpen() a.OnChannelPendingOpen()
} }
// HeuristicScores is an alias for a map that maps heuristic names to a map of
// scores for pubkeys.
type HeuristicScores map[string]map[NodeID]float64
// queryHeuristics gets node scores from all available simple heuristics, and
// the agent's current active heuristic.
func (a *Agent) queryHeuristics(nodes map[NodeID]struct{}) (
HeuristicScores, error) {
// Get the agent's current channel state.
a.chanStateMtx.Lock()
a.pendingMtx.Lock()
totalChans := mergeChanState(a.pendingOpens, a.chanState)
a.pendingMtx.Unlock()
a.chanStateMtx.Unlock()
// As channel size we'll use the maximum size.
chanSize := a.cfg.Constraints.MaxChanSize()
// We'll start by getting the scores from each available sub-heuristic,
// in addition the active agent heuristic.
report := make(HeuristicScores)
for _, h := range append(availableHeuristics, a.cfg.Heuristic) {
name := h.Name()
// If the active agent heuristic is among the simple heuristics
// it might get queried more than once. As an optimization
// we'll just skip it the second time.
if _, ok := report[name]; ok {
continue
}
s, err := h.NodeScores(
a.cfg.Graph, totalChans, chanSize, nodes,
)
if err != nil {
return nil, fmt.Errorf("unable to get sub score: %v", err)
}
log.Debugf("Heuristic \"%v\" scored %d nodes", name, len(s))
scores := make(map[NodeID]float64)
for nID, score := range s {
scores[nID] = score.Score
}
report[name] = scores
}
return report, nil
}

@ -269,23 +269,93 @@ func (m *Manager) StopAgent() error {
return nil return nil
} }
// QueryHeuristics queries the active autopilot agent for node scores. // QueryHeuristics queries the available autopilot heuristics for node scores.
func (m *Manager) QueryHeuristics(nodes []NodeID) (HeuristicScores, error) { func (m *Manager) QueryHeuristics(nodes []NodeID, localState bool) (
HeuristicScores, error) {
m.Lock() m.Lock()
defer m.Unlock() defer m.Unlock()
// Not active, so we can return early.
if m.pilot == nil {
return nil, fmt.Errorf("autopilot not active")
}
n := make(map[NodeID]struct{}) n := make(map[NodeID]struct{})
for _, node := range nodes { for _, node := range nodes {
n[node] = struct{}{} n[node] = struct{}{}
} }
log.Debugf("Querying heuristics for %d nodes", len(n)) log.Debugf("Querying heuristics for %d nodes", len(n))
return m.pilot.queryHeuristics(n) return m.queryHeuristics(n, localState)
}
// HeuristicScores is an alias for a map that maps heuristic names to a map of
// scores for pubkeys.
type HeuristicScores map[string]map[NodeID]float64
// queryHeuristics gets node scores from all available simple heuristics, and
// the agent's current active heuristic.
//
// NOTE: Must be called with the manager's lock.
func (m *Manager) queryHeuristics(nodes map[NodeID]struct{}, localState bool) (
HeuristicScores, error) {
// If we want to take the local state into action when querying the
// heuristics, we fetch it. If not we'll just pass an emply slice to
// the heuristic.
var totalChans []Channel
var err error
if localState {
// Fetch the current set of channels.
totalChans, err = m.cfg.ChannelState()
if err != nil {
return nil, err
}
// If the agent is active, we can merge the channel state with
// the channels pending open.
if m.pilot != nil {
m.pilot.chanStateMtx.Lock()
m.pilot.pendingMtx.Lock()
totalChans = mergeChanState(
m.pilot.pendingOpens, m.pilot.chanState,
)
m.pilot.pendingMtx.Unlock()
m.pilot.chanStateMtx.Unlock()
}
}
// As channel size we'll use the maximum size.
chanSize := m.cfg.PilotCfg.Constraints.MaxChanSize()
// We'll start by getting the scores from each available sub-heuristic,
// in addition the current agent heuristic.
report := make(HeuristicScores)
for _, h := range append(availableHeuristics, m.cfg.PilotCfg.Heuristic) {
name := h.Name()
// If the agent heuristic is among the simple heuristics it
// might get queried more than once. As an optimization we'll
// just skip it the second time.
if _, ok := report[name]; ok {
continue
}
s, err := h.NodeScores(
m.cfg.PilotCfg.Graph, totalChans, chanSize, nodes,
)
if err != nil {
return nil, fmt.Errorf("unable to get sub score: %v",
err)
}
log.Debugf("Heuristic \"%v\" scored %d nodes", name, len(s))
scores := make(map[NodeID]float64)
for nID, score := range s {
scores[nID] = score.Score
}
report[name] = scores
}
return report, nil
} }
// SetNodeScores is used to set the scores of the given heuristic, if it is // SetNodeScores is used to set the scores of the given heuristic, if it is

@ -97,9 +97,16 @@ func disable(ctx *cli.Context) error {
var queryScoresCommand = cli.Command{ var queryScoresCommand = cli.Command{
Name: "query", Name: "query",
Usage: "Query the autopilot heuristcs for nodes' scores.", Usage: "Query the autopilot heuristcs for nodes' scores.",
ArgsUsage: "<pubkey> <pubkey> <pubkey> ...", ArgsUsage: "[flags] <pubkey> <pubkey> <pubkey> ...",
Description: "", Description: "",
Action: actionDecorator(queryScores), Action: actionDecorator(queryScores),
Flags: []cli.Flag{
cli.BoolFlag{
Name: "ignorelocalstate, i",
Usage: "Ignore local channel state when calculating " +
"scores.",
},
},
} }
func queryScores(ctx *cli.Context) error { func queryScores(ctx *cli.Context) error {
@ -123,7 +130,8 @@ loop:
} }
req := &autopilotrpc.QueryScoresRequest{ req := &autopilotrpc.QueryScoresRequest{
Pubkeys: pubs, Pubkeys: pubs,
IgnoreLocalState: ctx.Bool("ignorelocalstate"),
} }
resp, err := client.QueryScores(ctxb, req) resp, err := client.QueryScores(ctxb, req)

@ -33,7 +33,7 @@ func (m *StatusRequest) Reset() { *m = StatusRequest{} }
func (m *StatusRequest) String() string { return proto.CompactTextString(m) } func (m *StatusRequest) String() string { return proto.CompactTextString(m) }
func (*StatusRequest) ProtoMessage() {} func (*StatusRequest) ProtoMessage() {}
func (*StatusRequest) Descriptor() ([]byte, []int) { func (*StatusRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_autopilot_569ccc5858bc499b, []int{0} return fileDescriptor_autopilot_1f7ac28ef56bb20c, []int{0}
} }
func (m *StatusRequest) XXX_Unmarshal(b []byte) error { func (m *StatusRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StatusRequest.Unmarshal(m, b) return xxx_messageInfo_StatusRequest.Unmarshal(m, b)
@ -65,7 +65,7 @@ func (m *StatusResponse) Reset() { *m = StatusResponse{} }
func (m *StatusResponse) String() string { return proto.CompactTextString(m) } func (m *StatusResponse) String() string { return proto.CompactTextString(m) }
func (*StatusResponse) ProtoMessage() {} func (*StatusResponse) ProtoMessage() {}
func (*StatusResponse) Descriptor() ([]byte, []int) { func (*StatusResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_autopilot_569ccc5858bc499b, []int{1} return fileDescriptor_autopilot_1f7ac28ef56bb20c, []int{1}
} }
func (m *StatusResponse) XXX_Unmarshal(b []byte) error { func (m *StatusResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StatusResponse.Unmarshal(m, b) return xxx_messageInfo_StatusResponse.Unmarshal(m, b)
@ -104,7 +104,7 @@ func (m *ModifyStatusRequest) Reset() { *m = ModifyStatusRequest{} }
func (m *ModifyStatusRequest) String() string { return proto.CompactTextString(m) } func (m *ModifyStatusRequest) String() string { return proto.CompactTextString(m) }
func (*ModifyStatusRequest) ProtoMessage() {} func (*ModifyStatusRequest) ProtoMessage() {}
func (*ModifyStatusRequest) Descriptor() ([]byte, []int) { func (*ModifyStatusRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_autopilot_569ccc5858bc499b, []int{2} return fileDescriptor_autopilot_1f7ac28ef56bb20c, []int{2}
} }
func (m *ModifyStatusRequest) XXX_Unmarshal(b []byte) error { func (m *ModifyStatusRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ModifyStatusRequest.Unmarshal(m, b) return xxx_messageInfo_ModifyStatusRequest.Unmarshal(m, b)
@ -141,7 +141,7 @@ func (m *ModifyStatusResponse) Reset() { *m = ModifyStatusResponse{} }
func (m *ModifyStatusResponse) String() string { return proto.CompactTextString(m) } func (m *ModifyStatusResponse) String() string { return proto.CompactTextString(m) }
func (*ModifyStatusResponse) ProtoMessage() {} func (*ModifyStatusResponse) ProtoMessage() {}
func (*ModifyStatusResponse) Descriptor() ([]byte, []int) { func (*ModifyStatusResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_autopilot_569ccc5858bc499b, []int{3} return fileDescriptor_autopilot_1f7ac28ef56bb20c, []int{3}
} }
func (m *ModifyStatusResponse) XXX_Unmarshal(b []byte) error { func (m *ModifyStatusResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ModifyStatusResponse.Unmarshal(m, b) return xxx_messageInfo_ModifyStatusResponse.Unmarshal(m, b)
@ -162,7 +162,9 @@ func (m *ModifyStatusResponse) XXX_DiscardUnknown() {
var xxx_messageInfo_ModifyStatusResponse proto.InternalMessageInfo var xxx_messageInfo_ModifyStatusResponse proto.InternalMessageInfo
type QueryScoresRequest struct { type QueryScoresRequest struct {
Pubkeys []string `protobuf:"bytes,1,rep,name=pubkeys,proto3" json:"pubkeys,omitempty"` Pubkeys []string `protobuf:"bytes,1,rep,name=pubkeys,proto3" json:"pubkeys,omitempty"`
// / If set, we will ignore the local channel state when calculating scores.
IgnoreLocalState bool `protobuf:"varint,2,opt,name=ignore_local_state,json=no_state,proto3" json:"ignore_local_state,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
@ -172,7 +174,7 @@ func (m *QueryScoresRequest) Reset() { *m = QueryScoresRequest{} }
func (m *QueryScoresRequest) String() string { return proto.CompactTextString(m) } func (m *QueryScoresRequest) String() string { return proto.CompactTextString(m) }
func (*QueryScoresRequest) ProtoMessage() {} func (*QueryScoresRequest) ProtoMessage() {}
func (*QueryScoresRequest) Descriptor() ([]byte, []int) { func (*QueryScoresRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_autopilot_569ccc5858bc499b, []int{4} return fileDescriptor_autopilot_1f7ac28ef56bb20c, []int{4}
} }
func (m *QueryScoresRequest) XXX_Unmarshal(b []byte) error { func (m *QueryScoresRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_QueryScoresRequest.Unmarshal(m, b) return xxx_messageInfo_QueryScoresRequest.Unmarshal(m, b)
@ -199,6 +201,13 @@ func (m *QueryScoresRequest) GetPubkeys() []string {
return nil return nil
} }
func (m *QueryScoresRequest) GetIgnoreLocalState() bool {
if m != nil {
return m.IgnoreLocalState
}
return false
}
type QueryScoresResponse struct { type QueryScoresResponse struct {
Results []*QueryScoresResponse_HeuristicResult `protobuf:"bytes,1,rep,name=results,proto3" json:"results,omitempty"` Results []*QueryScoresResponse_HeuristicResult `protobuf:"bytes,1,rep,name=results,proto3" json:"results,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
@ -210,7 +219,7 @@ func (m *QueryScoresResponse) Reset() { *m = QueryScoresResponse{} }
func (m *QueryScoresResponse) String() string { return proto.CompactTextString(m) } func (m *QueryScoresResponse) String() string { return proto.CompactTextString(m) }
func (*QueryScoresResponse) ProtoMessage() {} func (*QueryScoresResponse) ProtoMessage() {}
func (*QueryScoresResponse) Descriptor() ([]byte, []int) { func (*QueryScoresResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_autopilot_569ccc5858bc499b, []int{5} return fileDescriptor_autopilot_1f7ac28ef56bb20c, []int{5}
} }
func (m *QueryScoresResponse) XXX_Unmarshal(b []byte) error { func (m *QueryScoresResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_QueryScoresResponse.Unmarshal(m, b) return xxx_messageInfo_QueryScoresResponse.Unmarshal(m, b)
@ -249,7 +258,7 @@ func (m *QueryScoresResponse_HeuristicResult) Reset() { *m = QueryScores
func (m *QueryScoresResponse_HeuristicResult) String() string { return proto.CompactTextString(m) } func (m *QueryScoresResponse_HeuristicResult) String() string { return proto.CompactTextString(m) }
func (*QueryScoresResponse_HeuristicResult) ProtoMessage() {} func (*QueryScoresResponse_HeuristicResult) ProtoMessage() {}
func (*QueryScoresResponse_HeuristicResult) Descriptor() ([]byte, []int) { func (*QueryScoresResponse_HeuristicResult) Descriptor() ([]byte, []int) {
return fileDescriptor_autopilot_569ccc5858bc499b, []int{5, 0} return fileDescriptor_autopilot_1f7ac28ef56bb20c, []int{5, 0}
} }
func (m *QueryScoresResponse_HeuristicResult) XXX_Unmarshal(b []byte) error { func (m *QueryScoresResponse_HeuristicResult) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_QueryScoresResponse_HeuristicResult.Unmarshal(m, b) return xxx_messageInfo_QueryScoresResponse_HeuristicResult.Unmarshal(m, b)
@ -299,7 +308,7 @@ func (m *SetScoresRequest) Reset() { *m = SetScoresRequest{} }
func (m *SetScoresRequest) String() string { return proto.CompactTextString(m) } func (m *SetScoresRequest) String() string { return proto.CompactTextString(m) }
func (*SetScoresRequest) ProtoMessage() {} func (*SetScoresRequest) ProtoMessage() {}
func (*SetScoresRequest) Descriptor() ([]byte, []int) { func (*SetScoresRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_autopilot_569ccc5858bc499b, []int{6} return fileDescriptor_autopilot_1f7ac28ef56bb20c, []int{6}
} }
func (m *SetScoresRequest) XXX_Unmarshal(b []byte) error { func (m *SetScoresRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SetScoresRequest.Unmarshal(m, b) return xxx_messageInfo_SetScoresRequest.Unmarshal(m, b)
@ -343,7 +352,7 @@ func (m *SetScoresResponse) Reset() { *m = SetScoresResponse{} }
func (m *SetScoresResponse) String() string { return proto.CompactTextString(m) } func (m *SetScoresResponse) String() string { return proto.CompactTextString(m) }
func (*SetScoresResponse) ProtoMessage() {} func (*SetScoresResponse) ProtoMessage() {}
func (*SetScoresResponse) Descriptor() ([]byte, []int) { func (*SetScoresResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_autopilot_569ccc5858bc499b, []int{7} return fileDescriptor_autopilot_1f7ac28ef56bb20c, []int{7}
} }
func (m *SetScoresResponse) XXX_Unmarshal(b []byte) error { func (m *SetScoresResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_SetScoresResponse.Unmarshal(m, b) return xxx_messageInfo_SetScoresResponse.Unmarshal(m, b)
@ -573,37 +582,38 @@ var _Autopilot_serviceDesc = grpc.ServiceDesc{
} }
func init() { func init() {
proto.RegisterFile("autopilotrpc/autopilot.proto", fileDescriptor_autopilot_569ccc5858bc499b) proto.RegisterFile("autopilotrpc/autopilot.proto", fileDescriptor_autopilot_1f7ac28ef56bb20c)
} }
var fileDescriptor_autopilot_569ccc5858bc499b = []byte{ var fileDescriptor_autopilot_1f7ac28ef56bb20c = []byte{
// 439 bytes of a gzipped FileDescriptorProto // 463 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0x4d, 0x8b, 0xd3, 0x40, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0xcf, 0x6f, 0xd3, 0x30,
0x18, 0xc7, 0x99, 0x2c, 0x76, 0xcd, 0xd3, 0xd5, 0x5d, 0xa7, 0xcb, 0x12, 0x62, 0xd1, 0xee, 0x9c, 0x14, 0xc7, 0x95, 0x4c, 0x74, 0xcb, 0xeb, 0x60, 0xc3, 0x9d, 0xa6, 0x28, 0x54, 0xd0, 0x45, 0x1c,
0x8a, 0x60, 0x8a, 0xd5, 0x83, 0x0a, 0x1e, 0x5c, 0x11, 0x04, 0xf5, 0xe0, 0x94, 0xbd, 0x78, 0x4b, 0x2a, 0x24, 0x52, 0x51, 0x38, 0x00, 0x12, 0x07, 0x86, 0x90, 0x90, 0x80, 0x03, 0x2e, 0xbb, 0x70,
0xb2, 0x63, 0x3b, 0x34, 0xce, 0xc4, 0x79, 0x59, 0xc9, 0x17, 0xf2, 0xea, 0x67, 0xf0, 0xe8, 0xb7, 0x99, 0xd2, 0xcc, 0xb4, 0x56, 0x8d, 0x1d, 0xec, 0xe7, 0xa1, 0xfc, 0x43, 0x5c, 0xf9, 0x1b, 0x38,
0x92, 0x66, 0x92, 0x98, 0x84, 0x1a, 0x11, 0xbc, 0xe5, 0x79, 0xfb, 0x3d, 0x2f, 0xf9, 0x33, 0x30, 0xf2, 0x5f, 0xa1, 0xc5, 0x49, 0x49, 0xaa, 0x12, 0x84, 0xb4, 0x5b, 0xde, 0x8f, 0x7c, 0x9e, 0xdf,
0x8d, 0xad, 0x91, 0x39, 0xcf, 0xa4, 0x51, 0x79, 0xba, 0x68, 0x8c, 0x28, 0x57, 0xd2, 0x48, 0x7c, 0xd7, 0x5f, 0x19, 0x86, 0xa9, 0x45, 0x95, 0x73, 0xa1, 0x50, 0xe7, 0xd9, 0x64, 0x1d, 0x24, 0xb9,
0xd4, 0x8e, 0x92, 0x63, 0xb8, 0xb5, 0x32, 0xb1, 0xb1, 0x9a, 0xb2, 0x2f, 0x96, 0x69, 0x43, 0xe6, 0x56, 0xa8, 0xc8, 0x7e, 0xb3, 0x1a, 0x1f, 0xc0, 0xcd, 0x19, 0xa6, 0x68, 0x0d, 0x65, 0x5f, 0x2d,
0x70, 0xbb, 0x76, 0xe8, 0x5c, 0x0a, 0xcd, 0xf0, 0x19, 0x8c, 0xe2, 0xd4, 0xf0, 0x6b, 0x16, 0xa0, 0x33, 0x18, 0x8f, 0xe1, 0x56, 0x9d, 0x30, 0xb9, 0x92, 0x86, 0x91, 0x63, 0xe8, 0xa5, 0x19, 0xf2,
0x19, 0x9a, 0xdf, 0xa4, 0x95, 0x45, 0x1e, 0xc2, 0xe4, 0xbd, 0xbc, 0xe2, 0x9f, 0x8a, 0x0e, 0x60, 0x4b, 0x16, 0x7a, 0x23, 0x6f, 0xbc, 0x47, 0xab, 0x28, 0x7e, 0x08, 0x83, 0xf7, 0xea, 0x82, 0x7f,
0x97, 0xce, 0x44, 0x9c, 0x64, 0x4d, 0xba, 0xb3, 0xc8, 0x19, 0x9c, 0x76, 0xd3, 0x1d, 0x9e, 0x44, 0x2e, 0x5a, 0x80, 0xab, 0x76, 0x26, 0xd3, 0xb9, 0x58, 0xb7, 0xbb, 0x28, 0x3e, 0x86, 0xa3, 0x76,
0x80, 0x3f, 0x58, 0xa6, 0x8a, 0x55, 0x2a, 0x15, 0x6b, 0x28, 0x01, 0x1c, 0xe6, 0x36, 0xd9, 0xb2, 0xbb, 0xc3, 0xc7, 0x1f, 0x81, 0x7c, 0xb0, 0x4c, 0x17, 0xb3, 0x4c, 0x69, 0xb6, 0xa6, 0x84, 0xb0,
0x42, 0x07, 0x68, 0x76, 0x30, 0xf7, 0x69, 0x6d, 0x92, 0x6f, 0x1e, 0x4c, 0x3a, 0x05, 0xd5, 0x98, 0x9b, 0xdb, 0xf9, 0x8a, 0x15, 0x26, 0xf4, 0x46, 0x3b, 0xe3, 0x80, 0xd6, 0x21, 0xb9, 0x0f, 0x84,
0x6f, 0xe1, 0x50, 0x31, 0x6d, 0x33, 0xe3, 0x2a, 0xc6, 0xcb, 0x47, 0x51, 0x7b, 0xd3, 0x68, 0x4f, 0x2f, 0xa4, 0xd2, 0xec, 0x5c, 0xa8, 0x2c, 0x15, 0xe7, 0x06, 0x53, 0x64, 0xa1, 0x5f, 0xce, 0xda,
0x4d, 0xf4, 0x86, 0x59, 0xc5, 0xb5, 0xe1, 0x29, 0x2d, 0x2b, 0x69, 0x4d, 0x08, 0x7f, 0x20, 0x38, 0x93, 0xca, 0xc5, 0xf1, 0x77, 0x1f, 0x06, 0x2d, 0x6c, 0xb5, 0xcc, 0x5b, 0xd8, 0xd5, 0xcc, 0x58,
0xee, 0x05, 0xf1, 0x14, 0xfc, 0x4d, 0xed, 0x2a, 0x77, 0xf3, 0xe9, 0x6f, 0x07, 0xbe, 0x84, 0x91, 0x81, 0x8e, 0xdb, 0x9f, 0x3e, 0x4a, 0x9a, 0x7a, 0x24, 0x5b, 0xfe, 0x49, 0xde, 0x30, 0xab, 0xb9,
0x2e, 0xe1, 0x81, 0x57, 0x76, 0x7f, 0xf1, 0xcf, 0xdd, 0x23, 0x17, 0x7e, 0x2d, 0x8c, 0x2a, 0x68, 0x41, 0x9e, 0xd1, 0xf2, 0x4f, 0x5a, 0x13, 0xa2, 0x9f, 0x1e, 0x1c, 0x6c, 0x14, 0xc9, 0x10, 0x82,
0x05, 0x0b, 0x9f, 0xc1, 0xb8, 0xe5, 0xc6, 0x27, 0x70, 0xb0, 0x65, 0x45, 0xd5, 0x7d, 0xf7, 0x89, 0x65, 0x9d, 0x2a, 0x15, 0x08, 0xe8, 0x9f, 0x04, 0x39, 0x83, 0x9e, 0x29, 0xe1, 0xa1, 0x5f, 0x4e,
0x4f, 0xe1, 0xc6, 0x75, 0x9c, 0x59, 0x16, 0x78, 0x33, 0x34, 0x47, 0xd4, 0x19, 0xcf, 0xbd, 0xa7, 0x7f, 0xf1, 0xdf, 0xd3, 0x13, 0x57, 0x7e, 0x2d, 0x51, 0x17, 0xb4, 0x82, 0x45, 0xcf, 0xa0, 0xdf,
0x88, 0x7c, 0x47, 0x70, 0xb2, 0x62, 0xa6, 0x7b, 0xd7, 0xe1, 0x25, 0x2e, 0x7a, 0x4b, 0x3c, 0xe8, 0x48, 0x93, 0x43, 0xd8, 0x59, 0xb1, 0xa2, 0x9a, 0x7e, 0xf5, 0x49, 0x8e, 0xe0, 0xc6, 0x65, 0x2a,
0x2e, 0xd1, 0xa7, 0xfd, 0xef, 0x89, 0x27, 0x70, 0xa7, 0xd5, 0xc2, 0x5d, 0x69, 0xf9, 0xd3, 0x03, 0xac, 0xd3, 0xc9, 0xa3, 0x2e, 0x78, 0xee, 0x3f, 0xf5, 0xe2, 0x1f, 0x1e, 0x1c, 0xce, 0x18, 0xb6,
0xff, 0x65, 0x3d, 0x05, 0x7e, 0x05, 0x23, 0xa7, 0x1f, 0x7c, 0xb7, 0x37, 0x5b, 0x5b, 0x84, 0xe1, 0xd5, 0xef, 0x5e, 0xe2, 0x74, 0x63, 0x89, 0x07, 0xed, 0x25, 0x36, 0x69, 0xd7, 0x7d, 0xe2, 0x01,
0x74, 0x7f, 0xb0, 0x92, 0xca, 0x25, 0x1c, 0xb5, 0xa5, 0x88, 0xcf, 0xbb, 0xd9, 0x7b, 0x54, 0x1d, 0xdc, 0x6e, 0x8c, 0x70, 0x2a, 0x4d, 0x7f, 0xf9, 0x10, 0xbc, 0xac, 0x4f, 0x41, 0x5e, 0x41, 0xcf,
0x92, 0xa1, 0x94, 0x0a, 0x4b, 0x61, 0xdc, 0xfa, 0xcd, 0x78, 0x36, 0xa0, 0x00, 0x07, 0x3d, 0xff, 0xb9, 0x8c, 0xdc, 0xd9, 0x38, 0x5b, 0xd3, 0xaa, 0xd1, 0x70, 0x7b, 0xb1, 0xb2, 0xca, 0x19, 0xec,
0xab, 0x46, 0xf0, 0x3b, 0xf0, 0x9b, 0x93, 0xe0, 0x7b, 0xc3, 0xbf, 0x23, 0xbc, 0xff, 0xc7, 0xb8, 0x37, 0x0d, 0x4b, 0x4e, 0xda, 0xdd, 0x5b, 0xbc, 0x1f, 0xc5, 0x5d, 0x2d, 0x15, 0x96, 0x42, 0xbf,
0xa3, 0x5d, 0x3c, 0xf9, 0xb8, 0x5c, 0x73, 0xb3, 0xb1, 0x49, 0x94, 0xca, 0xcf, 0x8b, 0x8c, 0xaf, 0x71, 0xcd, 0x64, 0xd4, 0xe1, 0x00, 0x07, 0x3d, 0xf9, 0xa7, 0x47, 0xc8, 0x3b, 0x08, 0xd6, 0x92,
0x37, 0x46, 0x70, 0xb1, 0x16, 0xcc, 0x7c, 0x95, 0x6a, 0xbb, 0xc8, 0xc4, 0xd5, 0x22, 0x13, 0x9d, 0x90, 0xbb, 0xdd, 0xd7, 0x11, 0xdd, 0xfb, 0x6b, 0xdd, 0xd1, 0x4e, 0x9f, 0x7c, 0x9a, 0x2e, 0x38,
0x47, 0x43, 0xe5, 0x69, 0x32, 0x2a, 0x1f, 0x8e, 0xc7, 0xbf, 0x02, 0x00, 0x00, 0xff, 0xff, 0xcf, 0x2e, 0xed, 0x3c, 0xc9, 0xd4, 0x97, 0x89, 0xe0, 0x8b, 0x25, 0x4a, 0x2e, 0x17, 0x92, 0xe1, 0x37,
0x06, 0x7e, 0xe7, 0x58, 0x04, 0x00, 0x00, 0xa5, 0x57, 0x13, 0x21, 0x2f, 0x26, 0x42, 0xb6, 0x9e, 0x16, 0x9d, 0x67, 0xf3, 0x5e, 0xf9, 0xbc,
0x3c, 0xfe, 0x1d, 0x00, 0x00, 0xff, 0xff, 0xb1, 0x4e, 0x74, 0x27, 0x7e, 0x04, 0x00, 0x00,
} }

@ -50,6 +50,9 @@ message ModifyStatusResponse {}
message QueryScoresRequest{ message QueryScoresRequest{
repeated string pubkeys = 1 [json_name = "pubkeys"]; repeated string pubkeys = 1 [json_name = "pubkeys"];
/// If set, we will ignore the local channel state when calculating scores.
bool ignore_local_state = 2 [json_name = "no_state"];
} }
message QueryScoresResponse { message QueryScoresResponse {

@ -180,7 +180,9 @@ func (s *Server) QueryScores(ctx context.Context, in *QueryScoresRequest) (
} }
// Query the heuristics. // Query the heuristics.
heuristicScores, err := s.manager.QueryHeuristics(nodes) heuristicScores, err := s.manager.QueryHeuristics(
nodes, !in.IgnoreLocalState,
)
if err != nil { if err != nil {
return nil, err return nil, err
} }