Merge pull request #2350 from halseth/autopilot-dryrun-only
[Autopilot] Add heuristic dry-run option
This commit is contained in:
commit
ecd5541d55
@ -114,6 +114,7 @@ type Agent struct {
|
|||||||
|
|
||||||
// chanState tracks the current set of open channels.
|
// chanState tracks the current set of open channels.
|
||||||
chanState channelState
|
chanState channelState
|
||||||
|
chanStateMtx sync.Mutex
|
||||||
|
|
||||||
// stateUpdates is a channel that any external state updates that may
|
// stateUpdates is a channel that any external state updates that may
|
||||||
// affect the heuristics of the agent will be sent over.
|
// affect the heuristics of the agent will be sent over.
|
||||||
@ -410,7 +411,9 @@ func (a *Agent) controller() {
|
|||||||
spew.Sdump(update.newChan))
|
spew.Sdump(update.newChan))
|
||||||
|
|
||||||
newChan := update.newChan
|
newChan := update.newChan
|
||||||
|
a.chanStateMtx.Lock()
|
||||||
a.chanState[newChan.ChanID] = newChan
|
a.chanState[newChan.ChanID] = newChan
|
||||||
|
a.chanStateMtx.Unlock()
|
||||||
|
|
||||||
a.pendingMtx.Lock()
|
a.pendingMtx.Lock()
|
||||||
delete(a.pendingOpens, newChan.Node)
|
delete(a.pendingOpens, newChan.Node)
|
||||||
@ -424,9 +427,11 @@ func (a *Agent) controller() {
|
|||||||
"updates: %v",
|
"updates: %v",
|
||||||
spew.Sdump(update.closedChans))
|
spew.Sdump(update.closedChans))
|
||||||
|
|
||||||
|
a.chanStateMtx.Lock()
|
||||||
for _, closedChan := range update.closedChans {
|
for _, closedChan := range update.closedChans {
|
||||||
delete(a.chanState, closedChan)
|
delete(a.chanState, closedChan)
|
||||||
}
|
}
|
||||||
|
a.chanStateMtx.Unlock()
|
||||||
|
|
||||||
updateBalance()
|
updateBalance()
|
||||||
}
|
}
|
||||||
@ -472,10 +477,11 @@ func (a *Agent) controller() {
|
|||||||
// With all the updates applied, we'll obtain a set of the
|
// With all the updates applied, we'll obtain a set of the
|
||||||
// current active channels (confirmed channels), and also
|
// current active channels (confirmed channels), and also
|
||||||
// factor in our set of unconfirmed channels.
|
// factor in our set of unconfirmed channels.
|
||||||
confirmedChans := a.chanState
|
a.chanStateMtx.Lock()
|
||||||
a.pendingMtx.Lock()
|
a.pendingMtx.Lock()
|
||||||
totalChans := mergeChanState(a.pendingOpens, confirmedChans)
|
totalChans := mergeChanState(a.pendingOpens, a.chanState)
|
||||||
a.pendingMtx.Unlock()
|
a.pendingMtx.Unlock()
|
||||||
|
a.chanStateMtx.Unlock()
|
||||||
|
|
||||||
// Now that we've updated our internal state, we'll consult our
|
// Now that we've updated our internal state, we'll consult our
|
||||||
// channel attachment heuristic to determine if we can open
|
// channel attachment heuristic to determine if we can open
|
||||||
@ -514,7 +520,10 @@ func (a *Agent) openChans(availableFunds btcutil.Amount, numChans uint32,
|
|||||||
// We're to attempt an attachment so we'll obtain the set of
|
// We're to attempt an attachment so we'll obtain the set of
|
||||||
// nodes that we currently have channels with so we avoid
|
// nodes that we currently have channels with so we avoid
|
||||||
// duplicate edges.
|
// duplicate edges.
|
||||||
|
a.chanStateMtx.Lock()
|
||||||
connectedNodes := a.chanState.ConnectedNodes()
|
connectedNodes := a.chanState.ConnectedNodes()
|
||||||
|
a.chanStateMtx.Unlock()
|
||||||
|
|
||||||
a.pendingMtx.Lock()
|
a.pendingMtx.Lock()
|
||||||
nodesToSkip := mergeNodeMaps(a.pendingOpens,
|
nodesToSkip := mergeNodeMaps(a.pendingOpens,
|
||||||
a.pendingConns, connectedNodes, a.failedNodes,
|
a.pendingConns, connectedNodes, a.failedNodes,
|
||||||
@ -759,3 +768,55 @@ func (a *Agent) executeDirective(directive AttachmentDirective) {
|
|||||||
// we'll trigger the autopilot agent to query for more peers.
|
// we'll trigger the autopilot agent to query for more peers.
|
||||||
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
|
||||||
|
}
|
||||||
|
@ -80,6 +80,10 @@ type directiveArg struct {
|
|||||||
nodes map[NodeID]struct{}
|
nodes map[NodeID]struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *mockHeuristic) Name() string {
|
||||||
|
return "mock"
|
||||||
|
}
|
||||||
|
|
||||||
func (m *mockHeuristic) NodeScores(g ChannelGraph, chans []Channel,
|
func (m *mockHeuristic) NodeScores(g ChannelGraph, chans []Channel,
|
||||||
fundsAvailable btcutil.Amount, nodes map[NodeID]struct{}) (
|
fundsAvailable btcutil.Amount, nodes map[NodeID]struct{}) (
|
||||||
map[NodeID]*NodeScore, error) {
|
map[NodeID]*NodeScore, error) {
|
||||||
|
@ -47,6 +47,13 @@ func NewWeightedCombAttachment(h ...*WeightedHeuristic) (
|
|||||||
// AttachmentHeuristic interface.
|
// AttachmentHeuristic interface.
|
||||||
var _ AttachmentHeuristic = (*WeightedCombAttachment)(nil)
|
var _ AttachmentHeuristic = (*WeightedCombAttachment)(nil)
|
||||||
|
|
||||||
|
// Name returns the name of this heuristic.
|
||||||
|
//
|
||||||
|
// NOTE: This is a part of the AttachmentHeuristic interface.
|
||||||
|
func (c *WeightedCombAttachment) Name() string {
|
||||||
|
return "weightedcomb"
|
||||||
|
}
|
||||||
|
|
||||||
// NodeScores is a method that given the current channel graph, current set of
|
// NodeScores is a method that given the current channel graph, current set of
|
||||||
// local channels and funds available, scores the given nodes according to the
|
// local channels and funds available, scores the given nodes according to the
|
||||||
// preference of opening a channel with them. The returned channel candidates
|
// preference of opening a channel with them. The returned channel candidates
|
||||||
|
@ -119,6 +119,9 @@ type AttachmentDirective struct {
|
|||||||
// the interface is to allow an auto-pilot agent to decide if it needs more
|
// the interface is to allow an auto-pilot agent to decide if it needs more
|
||||||
// channels, and if so, which exact channels should be opened.
|
// channels, and if so, which exact channels should be opened.
|
||||||
type AttachmentHeuristic interface {
|
type AttachmentHeuristic interface {
|
||||||
|
// Name returns the name of this heuristic.
|
||||||
|
Name() string
|
||||||
|
|
||||||
// NodeScores is a method that given the current channel graph and
|
// NodeScores is a method that given the current channel graph and
|
||||||
// current set of local channels, scores the given nodes according to
|
// current set of local channels, scores the given nodes according to
|
||||||
// the preference of opening a channel of the given size with them. The
|
// the preference of opening a channel of the given size with them. The
|
||||||
@ -139,6 +142,27 @@ type AttachmentHeuristic interface {
|
|||||||
map[NodeID]*NodeScore, error)
|
map[NodeID]*NodeScore, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// availableHeuristics holds all heuristics possible to combine for use
|
||||||
|
// with the autopilot agent.
|
||||||
|
availableHeuristics = []AttachmentHeuristic{
|
||||||
|
NewPrefAttachment(),
|
||||||
|
}
|
||||||
|
|
||||||
|
// AvailableHeuristics is a map that holds the name of available
|
||||||
|
// heuristics to the actual heuristic for easy lookup. It will be
|
||||||
|
// filled during init().
|
||||||
|
AvailableHeuristics = make(map[string]AttachmentHeuristic)
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// Fill the map from heuristic names to available heuristics for easy
|
||||||
|
// lookup.
|
||||||
|
for _, h := range availableHeuristics {
|
||||||
|
AvailableHeuristics[h.Name()] = h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ChannelController is a simple interface that allows an auto-pilot agent to
|
// ChannelController is a simple interface that allows an auto-pilot agent to
|
||||||
// open a channel within the graph to a target peer, close targeted channels,
|
// open a channel within the graph to a target peer, close targeted channels,
|
||||||
// or add/remove funds from existing channels via a splice in/out mechanisms.
|
// or add/remove funds from existing channels via a splice in/out mechanisms.
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package autopilot
|
package autopilot
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
@ -267,3 +268,22 @@ func (m *Manager) StopAgent() error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryHeuristics queries the active autopilot agent for node scores.
|
||||||
|
func (m *Manager) QueryHeuristics(nodes []NodeID) (HeuristicScores, error) {
|
||||||
|
m.Lock()
|
||||||
|
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{})
|
||||||
|
for _, node := range nodes {
|
||||||
|
n[node] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debugf("Querying heuristics for %d nodes", len(n))
|
||||||
|
return m.pilot.queryHeuristics(n)
|
||||||
|
}
|
||||||
|
@ -43,6 +43,13 @@ func NewNodeID(pub *btcec.PublicKey) NodeID {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Name returns the name of this heuristic.
|
||||||
|
//
|
||||||
|
// NOTE: This is a part of the AttachmentHeuristic interface.
|
||||||
|
func (p *PrefAttachment) Name() string {
|
||||||
|
return "preferential"
|
||||||
|
}
|
||||||
|
|
||||||
// NodeScores is a method that given the current channel graph and current set
|
// NodeScores is a method that given the current channel graph and current set
|
||||||
// of local channels, scores the given nodes according to the preference of
|
// of local channels, scores the given nodes according to the preference of
|
||||||
// opening a channel of the given size with them. The returned channel
|
// opening a channel of the given size with them. The returned channel
|
||||||
|
@ -94,6 +94,47 @@ func disable(ctx *cli.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var queryScoresCommand = cli.Command{
|
||||||
|
Name: "query",
|
||||||
|
Usage: "Query the autopilot heuristcs for nodes' scores.",
|
||||||
|
ArgsUsage: "<pubkey> <pubkey> <pubkey> ...",
|
||||||
|
Description: "",
|
||||||
|
Action: actionDecorator(queryScores),
|
||||||
|
}
|
||||||
|
|
||||||
|
func queryScores(ctx *cli.Context) error {
|
||||||
|
ctxb := context.Background()
|
||||||
|
client, cleanUp := getAutopilotClient(ctx)
|
||||||
|
defer cleanUp()
|
||||||
|
|
||||||
|
args := ctx.Args()
|
||||||
|
var pubs []string
|
||||||
|
|
||||||
|
// Keep reading pubkeys as long as there are arguments.
|
||||||
|
loop:
|
||||||
|
for {
|
||||||
|
switch {
|
||||||
|
case args.Present():
|
||||||
|
pubs = append(pubs, args.First())
|
||||||
|
args = args.Tail()
|
||||||
|
default:
|
||||||
|
break loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
req := &autopilotrpc.QueryScoresRequest{
|
||||||
|
Pubkeys: pubs,
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.QueryScores(ctxb, req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
printRespJSON(resp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// autopilotCommands will return the set of commands to enable for autopilotrpc
|
// autopilotCommands will return the set of commands to enable for autopilotrpc
|
||||||
// builds.
|
// builds.
|
||||||
func autopilotCommands() []cli.Command {
|
func autopilotCommands() []cli.Command {
|
||||||
@ -107,6 +148,7 @@ func autopilotCommands() []cli.Command {
|
|||||||
getStatusCommand,
|
getStatusCommand,
|
||||||
enableCommand,
|
enableCommand,
|
||||||
disableCommand,
|
disableCommand,
|
||||||
|
queryScoresCommand,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -143,6 +143,7 @@ type bitcoindConfig struct {
|
|||||||
|
|
||||||
type autoPilotConfig struct {
|
type autoPilotConfig struct {
|
||||||
Active bool `long:"active" description:"If the autopilot agent should be active or not."`
|
Active bool `long:"active" description:"If the autopilot agent should be active or not."`
|
||||||
|
Heuristic map[string]float64 `long:"heuristic" description:"Heuristic to activate, and the weight to give it during scoring."`
|
||||||
MaxChannels int `long:"maxchannels" description:"The maximum number of channels that should be created"`
|
MaxChannels int `long:"maxchannels" description:"The maximum number of channels that should be created"`
|
||||||
Allocation float64 `long:"allocation" description:"The percentage of total funds that should be committed to automatic channel establishment"`
|
Allocation float64 `long:"allocation" description:"The percentage of total funds that should be committed to automatic channel establishment"`
|
||||||
MinChannelSize int64 `long:"minchansize" description:"The smallest channel that the autopilot agent should create"`
|
MinChannelSize int64 `long:"minchansize" description:"The smallest channel that the autopilot agent should create"`
|
||||||
@ -312,6 +313,9 @@ func loadConfig() (*config, error) {
|
|||||||
Allocation: 0.6,
|
Allocation: 0.6,
|
||||||
MinChannelSize: int64(minChanFundingSize),
|
MinChannelSize: int64(minChanFundingSize),
|
||||||
MaxChannelSize: int64(maxFundingAmount),
|
MaxChannelSize: int64(maxFundingAmount),
|
||||||
|
Heuristic: map[string]float64{
|
||||||
|
"preferential": 1.0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
TrickleDelay: defaultTrickleDelay,
|
TrickleDelay: defaultTrickleDelay,
|
||||||
InactiveChanTimeout: defaultInactiveChanTimeout,
|
InactiveChanTimeout: defaultInactiveChanTimeout,
|
||||||
@ -463,6 +467,10 @@ func loadConfig() (*config, error) {
|
|||||||
cfg.Autopilot.MaxChannelSize = int64(maxFundingAmount)
|
cfg.Autopilot.MaxChannelSize = int64(maxFundingAmount)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, err := validateAtplCfg(cfg.Autopilot); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// Validate the Tor config parameters.
|
// Validate the Tor config parameters.
|
||||||
socks, err := lncfg.ParseAddressString(
|
socks, err := lncfg.ParseAddressString(
|
||||||
cfg.Tor.SOCKS, strconv.Itoa(defaultTorSOCKSPort),
|
cfg.Tor.SOCKS, strconv.Itoa(defaultTorSOCKSPort),
|
||||||
|
@ -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_45e6f1df6dc1d1df, []int{0}
|
return fileDescriptor_autopilot_52f30cf4d0055211, []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_45e6f1df6dc1d1df, []int{1}
|
return fileDescriptor_autopilot_52f30cf4d0055211, []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_45e6f1df6dc1d1df, []int{2}
|
return fileDescriptor_autopilot_52f30cf4d0055211, []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_45e6f1df6dc1d1df, []int{3}
|
return fileDescriptor_autopilot_52f30cf4d0055211, []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)
|
||||||
@ -161,11 +161,137 @@ func (m *ModifyStatusResponse) XXX_DiscardUnknown() {
|
|||||||
|
|
||||||
var xxx_messageInfo_ModifyStatusResponse proto.InternalMessageInfo
|
var xxx_messageInfo_ModifyStatusResponse proto.InternalMessageInfo
|
||||||
|
|
||||||
|
type QueryScoresRequest struct {
|
||||||
|
Pubkeys []string `protobuf:"bytes,1,rep,name=pubkeys,proto3" json:"pubkeys,omitempty"`
|
||||||
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
XXX_sizecache int32 `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *QueryScoresRequest) Reset() { *m = QueryScoresRequest{} }
|
||||||
|
func (m *QueryScoresRequest) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*QueryScoresRequest) ProtoMessage() {}
|
||||||
|
func (*QueryScoresRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor_autopilot_52f30cf4d0055211, []int{4}
|
||||||
|
}
|
||||||
|
func (m *QueryScoresRequest) XXX_Unmarshal(b []byte) error {
|
||||||
|
return xxx_messageInfo_QueryScoresRequest.Unmarshal(m, b)
|
||||||
|
}
|
||||||
|
func (m *QueryScoresRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
|
return xxx_messageInfo_QueryScoresRequest.Marshal(b, m, deterministic)
|
||||||
|
}
|
||||||
|
func (dst *QueryScoresRequest) XXX_Merge(src proto.Message) {
|
||||||
|
xxx_messageInfo_QueryScoresRequest.Merge(dst, src)
|
||||||
|
}
|
||||||
|
func (m *QueryScoresRequest) XXX_Size() int {
|
||||||
|
return xxx_messageInfo_QueryScoresRequest.Size(m)
|
||||||
|
}
|
||||||
|
func (m *QueryScoresRequest) XXX_DiscardUnknown() {
|
||||||
|
xxx_messageInfo_QueryScoresRequest.DiscardUnknown(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
var xxx_messageInfo_QueryScoresRequest proto.InternalMessageInfo
|
||||||
|
|
||||||
|
func (m *QueryScoresRequest) GetPubkeys() []string {
|
||||||
|
if m != nil {
|
||||||
|
return m.Pubkeys
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type QueryScoresResponse struct {
|
||||||
|
Results []*QueryScoresResponse_HeuristicResult `protobuf:"bytes,1,rep,name=results,proto3" json:"results,omitempty"`
|
||||||
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
XXX_sizecache int32 `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *QueryScoresResponse) Reset() { *m = QueryScoresResponse{} }
|
||||||
|
func (m *QueryScoresResponse) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*QueryScoresResponse) ProtoMessage() {}
|
||||||
|
func (*QueryScoresResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor_autopilot_52f30cf4d0055211, []int{5}
|
||||||
|
}
|
||||||
|
func (m *QueryScoresResponse) XXX_Unmarshal(b []byte) error {
|
||||||
|
return xxx_messageInfo_QueryScoresResponse.Unmarshal(m, b)
|
||||||
|
}
|
||||||
|
func (m *QueryScoresResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
|
return xxx_messageInfo_QueryScoresResponse.Marshal(b, m, deterministic)
|
||||||
|
}
|
||||||
|
func (dst *QueryScoresResponse) XXX_Merge(src proto.Message) {
|
||||||
|
xxx_messageInfo_QueryScoresResponse.Merge(dst, src)
|
||||||
|
}
|
||||||
|
func (m *QueryScoresResponse) XXX_Size() int {
|
||||||
|
return xxx_messageInfo_QueryScoresResponse.Size(m)
|
||||||
|
}
|
||||||
|
func (m *QueryScoresResponse) XXX_DiscardUnknown() {
|
||||||
|
xxx_messageInfo_QueryScoresResponse.DiscardUnknown(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
var xxx_messageInfo_QueryScoresResponse proto.InternalMessageInfo
|
||||||
|
|
||||||
|
func (m *QueryScoresResponse) GetResults() []*QueryScoresResponse_HeuristicResult {
|
||||||
|
if m != nil {
|
||||||
|
return m.Results
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type QueryScoresResponse_HeuristicResult struct {
|
||||||
|
Heuristic string `protobuf:"bytes,1,opt,name=heuristic,proto3" json:"heuristic,omitempty"`
|
||||||
|
Scores map[string]float64 `protobuf:"bytes,2,rep,name=scores,proto3" json:"scores,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"fixed64,2,opt,name=value,proto3"`
|
||||||
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
XXX_sizecache int32 `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *QueryScoresResponse_HeuristicResult) Reset() { *m = QueryScoresResponse_HeuristicResult{} }
|
||||||
|
func (m *QueryScoresResponse_HeuristicResult) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*QueryScoresResponse_HeuristicResult) ProtoMessage() {}
|
||||||
|
func (*QueryScoresResponse_HeuristicResult) Descriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor_autopilot_52f30cf4d0055211, []int{5, 0}
|
||||||
|
}
|
||||||
|
func (m *QueryScoresResponse_HeuristicResult) XXX_Unmarshal(b []byte) error {
|
||||||
|
return xxx_messageInfo_QueryScoresResponse_HeuristicResult.Unmarshal(m, b)
|
||||||
|
}
|
||||||
|
func (m *QueryScoresResponse_HeuristicResult) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
|
return xxx_messageInfo_QueryScoresResponse_HeuristicResult.Marshal(b, m, deterministic)
|
||||||
|
}
|
||||||
|
func (dst *QueryScoresResponse_HeuristicResult) XXX_Merge(src proto.Message) {
|
||||||
|
xxx_messageInfo_QueryScoresResponse_HeuristicResult.Merge(dst, src)
|
||||||
|
}
|
||||||
|
func (m *QueryScoresResponse_HeuristicResult) XXX_Size() int {
|
||||||
|
return xxx_messageInfo_QueryScoresResponse_HeuristicResult.Size(m)
|
||||||
|
}
|
||||||
|
func (m *QueryScoresResponse_HeuristicResult) XXX_DiscardUnknown() {
|
||||||
|
xxx_messageInfo_QueryScoresResponse_HeuristicResult.DiscardUnknown(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
var xxx_messageInfo_QueryScoresResponse_HeuristicResult proto.InternalMessageInfo
|
||||||
|
|
||||||
|
func (m *QueryScoresResponse_HeuristicResult) GetHeuristic() string {
|
||||||
|
if m != nil {
|
||||||
|
return m.Heuristic
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *QueryScoresResponse_HeuristicResult) GetScores() map[string]float64 {
|
||||||
|
if m != nil {
|
||||||
|
return m.Scores
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
proto.RegisterType((*StatusRequest)(nil), "autopilotrpc.StatusRequest")
|
proto.RegisterType((*StatusRequest)(nil), "autopilotrpc.StatusRequest")
|
||||||
proto.RegisterType((*StatusResponse)(nil), "autopilotrpc.StatusResponse")
|
proto.RegisterType((*StatusResponse)(nil), "autopilotrpc.StatusResponse")
|
||||||
proto.RegisterType((*ModifyStatusRequest)(nil), "autopilotrpc.ModifyStatusRequest")
|
proto.RegisterType((*ModifyStatusRequest)(nil), "autopilotrpc.ModifyStatusRequest")
|
||||||
proto.RegisterType((*ModifyStatusResponse)(nil), "autopilotrpc.ModifyStatusResponse")
|
proto.RegisterType((*ModifyStatusResponse)(nil), "autopilotrpc.ModifyStatusResponse")
|
||||||
|
proto.RegisterType((*QueryScoresRequest)(nil), "autopilotrpc.QueryScoresRequest")
|
||||||
|
proto.RegisterType((*QueryScoresResponse)(nil), "autopilotrpc.QueryScoresResponse")
|
||||||
|
proto.RegisterType((*QueryScoresResponse_HeuristicResult)(nil), "autopilotrpc.QueryScoresResponse.HeuristicResult")
|
||||||
|
proto.RegisterMapType((map[string]float64)(nil), "autopilotrpc.QueryScoresResponse.HeuristicResult.ScoresEntry")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reference imports to suppress errors if they are not otherwise used.
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
@ -187,6 +313,11 @@ type AutopilotClient interface {
|
|||||||
// ModifyStatus is used to modify the status of the autopilot agent, like
|
// ModifyStatus is used to modify the status of the autopilot agent, like
|
||||||
// enabling or disabling it.
|
// enabling or disabling it.
|
||||||
ModifyStatus(ctx context.Context, in *ModifyStatusRequest, opts ...grpc.CallOption) (*ModifyStatusResponse, error)
|
ModifyStatus(ctx context.Context, in *ModifyStatusRequest, opts ...grpc.CallOption) (*ModifyStatusResponse, error)
|
||||||
|
// *
|
||||||
|
// QueryScores queries all available autopilot heuristics, in addition to any
|
||||||
|
// active combination of these heruristics, for the scores they would give to
|
||||||
|
// the given nodes.
|
||||||
|
QueryScores(ctx context.Context, in *QueryScoresRequest, opts ...grpc.CallOption) (*QueryScoresResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type autopilotClient struct {
|
type autopilotClient struct {
|
||||||
@ -215,6 +346,15 @@ func (c *autopilotClient) ModifyStatus(ctx context.Context, in *ModifyStatusRequ
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *autopilotClient) QueryScores(ctx context.Context, in *QueryScoresRequest, opts ...grpc.CallOption) (*QueryScoresResponse, error) {
|
||||||
|
out := new(QueryScoresResponse)
|
||||||
|
err := c.cc.Invoke(ctx, "/autopilotrpc.Autopilot/QueryScores", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
// AutopilotServer is the server API for Autopilot service.
|
// AutopilotServer is the server API for Autopilot service.
|
||||||
type AutopilotServer interface {
|
type AutopilotServer interface {
|
||||||
// *
|
// *
|
||||||
@ -224,6 +364,11 @@ type AutopilotServer interface {
|
|||||||
// ModifyStatus is used to modify the status of the autopilot agent, like
|
// ModifyStatus is used to modify the status of the autopilot agent, like
|
||||||
// enabling or disabling it.
|
// enabling or disabling it.
|
||||||
ModifyStatus(context.Context, *ModifyStatusRequest) (*ModifyStatusResponse, error)
|
ModifyStatus(context.Context, *ModifyStatusRequest) (*ModifyStatusResponse, error)
|
||||||
|
// *
|
||||||
|
// QueryScores queries all available autopilot heuristics, in addition to any
|
||||||
|
// active combination of these heruristics, for the scores they would give to
|
||||||
|
// the given nodes.
|
||||||
|
QueryScores(context.Context, *QueryScoresRequest) (*QueryScoresResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func RegisterAutopilotServer(s *grpc.Server, srv AutopilotServer) {
|
func RegisterAutopilotServer(s *grpc.Server, srv AutopilotServer) {
|
||||||
@ -266,6 +411,24 @@ func _Autopilot_ModifyStatus_Handler(srv interface{}, ctx context.Context, dec f
|
|||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _Autopilot_QueryScores_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(QueryScoresRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(AutopilotServer).QueryScores(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/autopilotrpc.Autopilot/QueryScores",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(AutopilotServer).QueryScores(ctx, req.(*QueryScoresRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
var _Autopilot_serviceDesc = grpc.ServiceDesc{
|
var _Autopilot_serviceDesc = grpc.ServiceDesc{
|
||||||
ServiceName: "autopilotrpc.Autopilot",
|
ServiceName: "autopilotrpc.Autopilot",
|
||||||
HandlerType: (*AutopilotServer)(nil),
|
HandlerType: (*AutopilotServer)(nil),
|
||||||
@ -278,30 +441,44 @@ var _Autopilot_serviceDesc = grpc.ServiceDesc{
|
|||||||
MethodName: "ModifyStatus",
|
MethodName: "ModifyStatus",
|
||||||
Handler: _Autopilot_ModifyStatus_Handler,
|
Handler: _Autopilot_ModifyStatus_Handler,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
MethodName: "QueryScores",
|
||||||
|
Handler: _Autopilot_QueryScores_Handler,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Streams: []grpc.StreamDesc{},
|
Streams: []grpc.StreamDesc{},
|
||||||
Metadata: "autopilotrpc/autopilot.proto",
|
Metadata: "autopilotrpc/autopilot.proto",
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
proto.RegisterFile("autopilotrpc/autopilot.proto", fileDescriptor_autopilot_45e6f1df6dc1d1df)
|
proto.RegisterFile("autopilotrpc/autopilot.proto", fileDescriptor_autopilot_52f30cf4d0055211)
|
||||||
}
|
}
|
||||||
|
|
||||||
var fileDescriptor_autopilot_45e6f1df6dc1d1df = []byte{
|
var fileDescriptor_autopilot_52f30cf4d0055211 = []byte{
|
||||||
// 226 bytes of a gzipped FileDescriptorProto
|
// 391 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x49, 0x2c, 0x2d, 0xc9,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x53, 0x4d, 0xaf, 0xd2, 0x40,
|
||||||
0x2f, 0xc8, 0xcc, 0xc9, 0x2f, 0x29, 0x2a, 0x48, 0xd6, 0x87, 0x73, 0xf4, 0x0a, 0x8a, 0xf2, 0x4b,
|
0x14, 0xcd, 0x94, 0x58, 0xec, 0x05, 0xc5, 0x0c, 0x84, 0x34, 0x95, 0x45, 0xe9, 0xaa, 0x1b, 0xdb,
|
||||||
0xf2, 0x85, 0x78, 0x90, 0x65, 0x95, 0xf8, 0xb9, 0x78, 0x83, 0x4b, 0x12, 0x4b, 0x4a, 0x8b, 0x83,
|
0x88, 0x2e, 0xd4, 0xc4, 0x85, 0x1a, 0x13, 0x13, 0xe3, 0xc2, 0x21, 0x6c, 0xdc, 0xb5, 0x65, 0x84,
|
||||||
0x52, 0x0b, 0x4b, 0x53, 0x8b, 0x4b, 0x94, 0x34, 0xb8, 0xf8, 0x60, 0x02, 0xc5, 0x05, 0xf9, 0x79,
|
0x09, 0x75, 0xa6, 0xce, 0x07, 0xa6, 0x7f, 0xc8, 0xff, 0xe1, 0xef, 0x72, 0xf3, 0x42, 0x3f, 0x78,
|
||||||
0xc5, 0xa9, 0x42, 0x62, 0x5c, 0x6c, 0x89, 0xc9, 0x25, 0x99, 0x65, 0xa9, 0x12, 0x8c, 0x0a, 0x8c,
|
0xed, 0x0b, 0xe1, 0xe5, 0xed, 0x7a, 0xee, 0x3d, 0xe7, 0xdc, 0x3b, 0x67, 0x3a, 0xb0, 0x48, 0x8c,
|
||||||
0x1a, 0x1c, 0x41, 0x50, 0x9e, 0x92, 0x2e, 0x97, 0xb0, 0x6f, 0x7e, 0x4a, 0x66, 0x5a, 0x25, 0x8a,
|
0x16, 0x05, 0xcb, 0x85, 0x96, 0x45, 0x16, 0x9f, 0x41, 0x54, 0x48, 0xa1, 0x05, 0x1e, 0x77, 0xbb,
|
||||||
0x01, 0x20, 0xe5, 0xa9, 0x79, 0x89, 0x49, 0x39, 0x70, 0xe5, 0x10, 0x9e, 0x92, 0x18, 0x97, 0x08,
|
0xc1, 0x04, 0x9e, 0xac, 0x75, 0xa2, 0x8d, 0x22, 0xf4, 0xb7, 0xa1, 0x4a, 0x07, 0x21, 0x3c, 0x6d,
|
||||||
0xaa, 0x72, 0x88, 0xf1, 0x46, 0xcb, 0x19, 0xb9, 0x38, 0x1d, 0x61, 0x4e, 0x12, 0x72, 0xe6, 0x62,
|
0x0b, 0xaa, 0x10, 0x5c, 0x51, 0x3c, 0x07, 0x3b, 0xc9, 0x34, 0x3b, 0x52, 0x17, 0xf9, 0x28, 0x7c,
|
||||||
0x83, 0xc8, 0x0b, 0x49, 0xeb, 0x21, 0x3b, 0x54, 0x0f, 0xc5, 0x12, 0x29, 0x19, 0xec, 0x92, 0x50,
|
0x4c, 0x1a, 0x14, 0xbc, 0x80, 0xe9, 0x37, 0xb1, 0x65, 0x3f, 0xcb, 0x9e, 0xc1, 0x89, 0x4e, 0x79,
|
||||||
0x17, 0x87, 0x72, 0xf1, 0x20, 0x5b, 0x25, 0xa4, 0x88, 0xaa, 0x1a, 0x8b, 0xab, 0xa5, 0x94, 0xf0,
|
0x92, 0xe6, 0x67, 0x7a, 0x8d, 0x82, 0x39, 0xcc, 0xfa, 0xf4, 0xda, 0x3e, 0x88, 0x00, 0x7f, 0x37,
|
||||||
0x29, 0x81, 0x18, 0xeb, 0x64, 0x12, 0x65, 0x94, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c,
|
0x54, 0x96, 0xeb, 0x4c, 0x48, 0x7a, 0x76, 0x71, 0x61, 0x58, 0x98, 0xf4, 0x40, 0x4b, 0xe5, 0x22,
|
||||||
0x9f, 0xab, 0x9f, 0x93, 0x99, 0x9e, 0x51, 0x92, 0x97, 0x99, 0x97, 0x9e, 0x97, 0x5a, 0x52, 0x9e,
|
0x7f, 0x10, 0x3a, 0xa4, 0x85, 0xc1, 0x5f, 0x0b, 0xa6, 0x3d, 0x41, 0xb3, 0xe6, 0x57, 0x18, 0x4a,
|
||||||
0x5f, 0x94, 0xad, 0x9f, 0x93, 0x97, 0xa2, 0x9f, 0x93, 0x87, 0x12, 0xe4, 0x45, 0x05, 0xc9, 0x49,
|
0xaa, 0x4c, 0xae, 0x6b, 0xc5, 0x68, 0xf5, 0x32, 0xea, 0x9e, 0x34, 0xba, 0xa0, 0x89, 0xbe, 0x50,
|
||||||
0x6c, 0xe0, 0x60, 0x37, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0xd1, 0x71, 0xb3, 0xba, 0x96, 0x01,
|
0x23, 0x99, 0xd2, 0x2c, 0x23, 0x95, 0x92, 0xb4, 0x0e, 0xde, 0x3f, 0x04, 0x93, 0x3b, 0x4d, 0xbc,
|
||||||
0x00, 0x00,
|
0x00, 0x67, 0xdf, 0x96, 0xaa, 0xb3, 0x39, 0xe4, 0xb6, 0x80, 0x37, 0x60, 0xab, 0xca, 0xdc, 0xb5,
|
||||||
|
0xaa, 0xe9, 0xef, 0x1f, 0x3c, 0x3d, 0xaa, 0xdb, 0x9f, 0xb9, 0x96, 0x25, 0x69, 0xcc, 0xbc, 0xb7,
|
||||||
|
0x30, 0xea, 0x94, 0xf1, 0x33, 0x18, 0x1c, 0x68, 0xd9, 0x4c, 0x3f, 0x7d, 0xe2, 0x19, 0x3c, 0x3a,
|
||||||
|
0x26, 0xb9, 0xa1, 0xae, 0xe5, 0xa3, 0x10, 0x91, 0x1a, 0xbc, 0xb3, 0xde, 0xa0, 0xd5, 0x7f, 0x04,
|
||||||
|
0xce, 0x87, 0x76, 0x07, 0xfc, 0x09, 0xec, 0x3a, 0x78, 0xfc, 0xbc, 0xbf, 0x59, 0xef, 0xf6, 0xbc,
|
||||||
|
0xc5, 0xe5, 0x66, 0x93, 0xf1, 0x06, 0xc6, 0xdd, 0x3b, 0xc4, 0xcb, 0x3e, 0xfb, 0xc2, 0xef, 0xe0,
|
||||||
|
0x05, 0xd7, 0x28, 0x8d, 0x2d, 0x81, 0x51, 0x27, 0x1f, 0xec, 0x5f, 0x89, 0xae, 0x36, 0x5d, 0xde,
|
||||||
|
0x1b, 0xee, 0xc7, 0xd7, 0x3f, 0x56, 0x3b, 0xa6, 0xf7, 0x26, 0x8d, 0x32, 0xf1, 0x2b, 0xce, 0xd9,
|
||||||
|
0x6e, 0xaf, 0x39, 0xe3, 0x3b, 0x4e, 0xf5, 0x1f, 0x21, 0x0f, 0x71, 0xce, 0xb7, 0x71, 0xce, 0x7b,
|
||||||
|
0xef, 0x43, 0x16, 0x59, 0x6a, 0x57, 0x6f, 0xe4, 0xd5, 0x4d, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa1,
|
||||||
|
0xe9, 0x30, 0xf3, 0x43, 0x03, 0x00, 0x00,
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,13 @@ service Autopilot {
|
|||||||
enabling or disabling it.
|
enabling or disabling it.
|
||||||
*/
|
*/
|
||||||
rpc ModifyStatus(ModifyStatusRequest) returns (ModifyStatusResponse);
|
rpc ModifyStatus(ModifyStatusRequest) returns (ModifyStatusResponse);
|
||||||
|
|
||||||
|
/**
|
||||||
|
QueryScores queries all available autopilot heuristics, in addition to any
|
||||||
|
active combination of these heruristics, for the scores they would give to
|
||||||
|
the given nodes.
|
||||||
|
*/
|
||||||
|
rpc QueryScores(QueryScoresRequest) returns (QueryScoresResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
message StatusRequest{
|
message StatusRequest{
|
||||||
@ -34,3 +41,16 @@ message ModifyStatusRequest{
|
|||||||
}
|
}
|
||||||
|
|
||||||
message ModifyStatusResponse {}
|
message ModifyStatusResponse {}
|
||||||
|
|
||||||
|
message QueryScoresRequest{
|
||||||
|
repeated string pubkeys = 1 [json_name = "pubkeys"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message QueryScoresResponse {
|
||||||
|
message HeuristicResult {
|
||||||
|
string heuristic = 1 [json_name = "heuristic"];
|
||||||
|
map<string, double> scores= 2 [json_name = "scores"];
|
||||||
|
}
|
||||||
|
|
||||||
|
repeated HeuristicResult results = 1 [json_name = "results"];
|
||||||
|
}
|
||||||
|
@ -4,9 +4,11 @@ package autopilotrpc
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/hex"
|
||||||
"os"
|
"os"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
|
"github.com/btcsuite/btcd/btcec"
|
||||||
"github.com/lightningnetwork/lnd/autopilot"
|
"github.com/lightningnetwork/lnd/autopilot"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
@ -35,6 +37,10 @@ var (
|
|||||||
Entity: "offchain",
|
Entity: "offchain",
|
||||||
Action: "write",
|
Action: "write",
|
||||||
}},
|
}},
|
||||||
|
"/autopilotrpc.Autopilot/QueryScores": {{
|
||||||
|
Entity: "info",
|
||||||
|
Action: "read",
|
||||||
|
}},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -154,3 +160,60 @@ func (s *Server) ModifyStatus(ctx context.Context,
|
|||||||
}
|
}
|
||||||
return &ModifyStatusResponse{}, err
|
return &ModifyStatusResponse{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryScores queries all available autopilot heuristics, in addition to any
|
||||||
|
// active combination of these heruristics, for the scores they would give to
|
||||||
|
// the given nodes.
|
||||||
|
//
|
||||||
|
// NOTE: Part of the AutopilotServer interface.
|
||||||
|
func (s *Server) QueryScores(ctx context.Context, in *QueryScoresRequest) (
|
||||||
|
*QueryScoresResponse, error) {
|
||||||
|
|
||||||
|
var nodes []autopilot.NodeID
|
||||||
|
for _, pubStr := range in.Pubkeys {
|
||||||
|
pubHex, err := hex.DecodeString(pubStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pubKey, err := btcec.ParsePubKey(pubHex, btcec.S256())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
nID := autopilot.NewNodeID(pubKey)
|
||||||
|
nodes = append(nodes, nID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query the heuristics.
|
||||||
|
heuristicScores, err := s.manager.QueryHeuristics(nodes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := &QueryScoresResponse{}
|
||||||
|
for heuristic, scores := range heuristicScores {
|
||||||
|
result := &QueryScoresResponse_HeuristicResult{
|
||||||
|
Heuristic: heuristic,
|
||||||
|
Scores: make(map[string]float64),
|
||||||
|
}
|
||||||
|
|
||||||
|
for pub, score := range scores {
|
||||||
|
pubkeyHex := hex.EncodeToString(pub[:])
|
||||||
|
result.Scores[pubkeyHex] = score
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since a node not being part of the internally returned
|
||||||
|
// scores imply a zero score, we add these before we return the
|
||||||
|
// RPC results.
|
||||||
|
for _, node := range nodes {
|
||||||
|
if _, ok := scores[node]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pubkeyHex := hex.EncodeToString(node[:])
|
||||||
|
result.Scores[pubkeyHex] = 0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.Results = append(resp.Results, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
66
pilot.go
66
pilot.go
@ -14,6 +14,60 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/tor"
|
"github.com/lightningnetwork/lnd/tor"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// validateAtplConfig is a helper method that makes sure the passed
|
||||||
|
// configuration is sane. Currently it checks that the heuristic configuration
|
||||||
|
// makes sense. In case the config is valid, it will return a list of
|
||||||
|
// WeightedHeuristics that can be combined for use with the autopilot agent.
|
||||||
|
func validateAtplCfg(cfg *autoPilotConfig) ([]*autopilot.WeightedHeuristic,
|
||||||
|
error) {
|
||||||
|
|
||||||
|
var (
|
||||||
|
heuristicsStr string
|
||||||
|
sum float64
|
||||||
|
heuristics []*autopilot.WeightedHeuristic
|
||||||
|
)
|
||||||
|
|
||||||
|
// Create a help text that we can return in case the config is not
|
||||||
|
// correct.
|
||||||
|
for _, a := range autopilot.AvailableHeuristics {
|
||||||
|
heuristicsStr += fmt.Sprintf(" '%v' ", a.Name())
|
||||||
|
}
|
||||||
|
availStr := fmt.Sprintf("Avaiblable heuristcs are: [%v]", heuristicsStr)
|
||||||
|
|
||||||
|
// We'll go through the config and make sure all the heuristics exists,
|
||||||
|
// and that the sum of their weights is 1.0.
|
||||||
|
for name, weight := range cfg.Heuristic {
|
||||||
|
a, ok := autopilot.AvailableHeuristics[name]
|
||||||
|
if !ok {
|
||||||
|
// No heuristic matching this config option was found.
|
||||||
|
return nil, fmt.Errorf("Heuristic %v not available. %v",
|
||||||
|
name, availStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this heuristic was among the registered ones, we add it
|
||||||
|
// to the list we'll give to the agent, and keep track of the
|
||||||
|
// sum of weights.
|
||||||
|
heuristics = append(
|
||||||
|
heuristics,
|
||||||
|
&autopilot.WeightedHeuristic{
|
||||||
|
Weight: weight,
|
||||||
|
AttachmentHeuristic: a,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
sum += weight
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check found heuristics. We must have at least one to operate.
|
||||||
|
if len(heuristics) == 0 {
|
||||||
|
return nil, fmt.Errorf("No active heuristics. %v", availStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if sum != 1.0 {
|
||||||
|
return nil, fmt.Errorf("Heuristic weights must sum to 1.0")
|
||||||
|
}
|
||||||
|
return heuristics, nil
|
||||||
|
}
|
||||||
|
|
||||||
// chanController is an implementation of the autopilot.ChannelController
|
// chanController is an implementation of the autopilot.ChannelController
|
||||||
// interface that's backed by a running lnd instance.
|
// interface that's backed by a running lnd instance.
|
||||||
type chanController struct {
|
type chanController struct {
|
||||||
@ -94,15 +148,13 @@ func initAutoPilot(svr *server, cfg *autoPilotConfig) (*autopilot.ManagerCfg, er
|
|||||||
10,
|
10,
|
||||||
cfg.Allocation,
|
cfg.Allocation,
|
||||||
)
|
)
|
||||||
|
heuristics, err := validateAtplCfg(cfg)
|
||||||
// First, we'll create the preferential attachment heuristic.
|
if err != nil {
|
||||||
prefAttachment := autopilot.NewPrefAttachment()
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
weightedAttachment, err := autopilot.NewWeightedCombAttachment(
|
weightedAttachment, err := autopilot.NewWeightedCombAttachment(
|
||||||
&autopilot.WeightedHeuristic{
|
heuristics...,
|
||||||
Weight: 1.0,
|
|
||||||
AttachmentHeuristic: prefAttachment,
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
Loading…
Reference in New Issue
Block a user