Skip to content

Conversation

@feelancer21
Copy link
Owner

v2 of PoC PR

Chnge Description

Description of change / link to associated issue.

Steps to Test

Steps for reviewers to follow to test the change.

Pull Request Checklist

Testing

  • Your PR passes all CI checks.
  • Tests covering the positive and negative (error paths) are included.
  • Bug fixes contain tests triggering the bug to prevent regressions.

Code Style and Documentation

📝 Please see our Contribution Guidelines for further guidance.

Copilot AI review requested due to automatic review settings July 25, 2025 21:58
@github-actions
Copy link

Pull reviewers stats

Stats of the last 30 days for lnd:

User Total reviews Time to review Total comments

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary of Changes

Hello @feelancer21, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a significant new feature that allows users to influence Lightning Network routing decisions by defining and applying 'imputed costs'. These are virtual costs or penalties assigned to specific node pairs, which are then factored into the pathfinding algorithm. The primary purpose is to provide a flexible mechanism for users to guide route selection based on their own criteria, beyond just standard routing fees. This is a proof-of-concept (v2) that lays the groundwork for more sophisticated routing strategies, enabling users to prioritize certain paths or avoid others based on custom cost models. The imputed costs are currently in-memory only and not persisted across restarts.

Highlights

  • New Imputed Cost Restriction for Routing and Payments: I've introduced a new ImputedCostRestriction message and integrated it into QueryRoutesRequest and SendPaymentRequest. This allows users to specify virtual cost criteria, including a namespace and a total cost limit, when querying for routes or sending payments.
  • Experimental RPCs for Imputed Cost Management: I've added three new experimental RPCs to the routerrpc.Router service: XImportImputedCosts, XQueryImputedCosts, and XDeleteImputedCosts. These APIs enable users to programmatically manage in-memory imputed cost configurations, influencing routing decisions without affecting actual network fees.
  • Centralized Imputed Cost Management System: A new ImputedCostManager component has been implemented to handle the storage and retrieval of imputed cost namespaces and their associated parameters. This manager provides the core logic for applying virtual costs during pathfinding and is integrated across various routing components.
  • Integration of Imputed Costs into Pathfinding Algorithm: The pathfinding algorithm (findPath) has been updated to incorporate imputedDistInfo and utilize an ImputedCostControl. This allows the algorithm to consider and apply these virtual costs, dynamically adjusting path selection based on user-defined preferences and ensuring cost limits are respected.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments or fill out our survey to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces an imputed costs feature for routing decisions in the Lightning Network. Imputed costs allow users to apply additional virtual costs or penalties to specific node pairs to influence route selection without modifying actual network fees.

  • Adds a new ImputedCostManager with namespace-based cost configurations
  • Integrates imputed cost calculations into the pathfinding algorithm
  • Provides new gRPC APIs for importing, querying, and deleting imputed cost configurations

Reviewed Changes

Copilot reviewed 20 out of 22 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
server.go Initializes ImputedCostManager and integrates it into server routing components
rpcserver.go Adds ImputedCostManager to RPC server dependencies
routing/router.go Adds ImputedCostRestriction field to LightningPayment struct
routing/payment_session.go Integrates imputed cost control into payment session route requests
routing/pathfind.go Implements imputed cost calculations in the pathfinding algorithm
routing/imputed_cost.go Core implementation of imputed cost manager and related types
routing/imputed_cost_test.go Comprehensive test suite for imputed cost functionality
routing/heap.go Adds imputedDistInfo field to nodeWithDist struct
lnrpc/routerrpc/* Generated gRPC code for new imputed cost APIs
lnrpc/lightning.proto Adds ImputedCostRestriction message to QueryRoutesRequest

return res, nil
}

// ImputedCostParameters defines the cost parameters for a node pair, mirroring
Copy link

Copilot AI Jul 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment contains a capitalization inconsistency. 'ImputedCostParameters' should be 'imputedCostParameters' to match the actual struct name on line 123.

Suggested change
// ImputedCostParameters defines the cost parameters for a node pair, mirroring
// imputedCostParameters defines the cost parameters for a node pair, mirroring

Copilot uses AI. Check for mistakes.
// will happen and this value remains unused.
minShardAmt lnwire.MilliSatoshi

// replace with Interface?
Copy link

Copilot AI Jul 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This TODO comment should be removed or expanded into a proper TODO with context about what interface should be used and why.

Suggested change
// replace with Interface?
// TODO: Consider replacing ImputedCostManager with an interface to improve
// modularity and testability. This would allow different implementations
// of cost management to be injected, making the code more flexible and
// easier to test. Define an interface that includes the required methods
// from ImputedCostManager and update the code accordingly if needed.

Copilot uses AI. Check for mistakes.
ShouldSetExpEndorsement func() bool

// Provides access to the ImputedCostNamespaces.
// Question: Replace with interface?
Copy link

Copilot AI Jul 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This question comment should be removed or converted to a proper TODO with specific details about what interface should be considered.

Suggested change
// Question: Replace with interface?
// TODO: Evaluate whether ImputedCostManager should be replaced with an interface

Copilot uses AI. Check for mistakes.
fromNode := m.selfNode

for _, hop := range attempt.Route.Hops {
// TODO(feelancer21): Think about the correct amount!!!
Copy link

Copilot AI Jul 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This TODO comment is unclear and uses excessive exclamation marks. It should specify what needs to be considered about the amount calculation.

Suggested change
// TODO(feelancer21): Think about the correct amount!!!
// TODO(feelancer21): Determine the correct amount to use for cost calculation.
// Consider how hop.AmtToForward interacts with the cost model and ensure
// that the calculation aligns with the expected behavior of the payment routing.

Copilot uses AI. Check for mistakes.
p.payment.ImputedCostRestriction,
)
if err != nil {
return nil, errNoPathFound
Copy link

Copilot AI Jul 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When imputed cost manager fails to get payment control, returning 'errNoPathFound' is misleading. This should return the actual error from GetPaymentControl to provide better debugging information.

Suggested change
return nil, errNoPathFound
return nil, err

Copilot uses AI. Check for mistakes.
Comment on lines +1125 to +1128
paymentControl := channeldb.NewPaymentControl(dbs.ChanStateDB)

s.controlTower = routing.NewControlTower(paymentControl)

Copy link

Copilot AI Jul 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The paymentControl and controlTower initialization has been moved up, but the original location is still shown with removal markers. This creates duplicate initialization of these components, which could lead to bugs.

Suggested change
paymentControl := channeldb.NewPaymentControl(dbs.ChanStateDB)
s.controlTower = routing.NewControlTower(paymentControl)
// Removed duplicate initialization of paymentControl and controlTower.

Copilot uses AI. Check for mistakes.
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the concept of "imputed costs" to influence route selection in the pathfinding algorithm. It adds new RPCs for managing imputed cost data and integrates this data into the payment and routing logic. The changes are well-structured and include new logic for cost calculation, management, and corresponding tests. My review focuses on adherence to the provided style guide, potential improvements for code clarity and testability, and some design considerations that might be worth discussing.

fromNode := m.selfNode

for _, hop := range attempt.Route.Hops {
// TODO(feelancer21): Think about the correct amount!!!

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

This TODO comment indicates uncertainty about the correctness of the amount being used. This should be resolved before merging, as it could affect the accuracy of cost calculations.

Comment on lines +211 to +221
XQueryImputedCosts is an experimental API that retrieves the currently
active imputed cost configurations for the specified namespaces. If no
namespaces are specified, all configured namespaces will be returned.
*/
rpc XQueryImputedCosts (QueryImputedCostsRequest)
returns (QueryImputedCostsResponse);

/*
XDeleteImputedCosts is an experimental API that permanently removes the
specified namespaces and all their associated imputed cost configurations.
*/

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

These comments exceed the 80-character line length limit specified in the style guide.1

Style Guide References

Footnotes

  1. The style guide requires that all lines must not exceed 80 characters. (link)

Comment on lines +1194 to +1219

message ImputedCostParameters {
// Success-based imputed cost rate in parts per million (ppm) of the amount
// sent. These virtual costs are only applied when the payment succeeds,
// and due to pathfinding algorithm constraints, only non-negative values
// are currently supported.
int32 cost_rate_ppm = 1;

// Success-based base imputed cost in millisatoshis. This fixed virtual cost
// is only applied when the payment succeeds, regardless of the payment
// amount. Due to pathfinding algorithm constraints, only non-negative
// values are currently supported.
int32 cost_base_msat = 2;

// Attempt-based imputed cost rate in parts per million (ppm) of the amount
// sent. These virtual costs are applied for every routing attempt through
// this node pair, regardless of whether the payment ultimately succeeds or
// fails. Due to pathfinding algorithm constraints, only non-negative values
// are currently supported.
int32 attempt_cost_rate_ppm = 3;

// Attempt-based base imputed cost in millisatoshis. This fixed virtual cost
// is applied for every routing attempt through this node pair, regardless
// of the payment amount or ultimate success/failure. Due to pathfinding
// algorithm constraints, only non-negative values are currently supported.
int32 attempt_cost_base_msat = 4;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The comments for these fields state that only non-negative values are currently supported. Using int32 allows negative values, which could be misleading. Consider using uint32 to enforce this constraint at the protobuf level, or add validation logic in the application layer. If negative values are planned for future use, this can be left as is, but it's worth a discussion.


// Provides access to the ImputedCostNamespaces.
// Question: Replace with interface?
ImputedCostManager *routing.ImputedCostManager

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The comment here raises a valid point. Using an interface for ImputedCostManager instead of a concrete type would improve testability and decoupling. It's a good practice to depend on abstractions rather than concretions. I recommend making this change.

Comment on lines 208 to 209
return nil, fmt.Errorf("total cost limit must be non-negative:"+
" %d", restr.TotalCostLimitMsat)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This error message formatting violates the style guide for long error messages.1 It should be on a single line with string concatenation.

Style Guide References

Suggested change
return nil, fmt.Errorf("total cost limit must be non-negative:"+
" %d", restr.TotalCostLimitMsat)
return nil, fmt.Errorf("total cost limit must be non-negative: %d",
restr.TotalCostLimitMsat)

Footnotes

  1. The style guide specifies that long error messages should be formatted on a single line using string concatenation to adhere to the 80-character limit. (link)

Comment on lines +334 to +370
func (m *ImputedCostManager) calcShardLimit(paymentHash lntypes.Hash, shardAmt,
costLimit lnwire.MilliSatoshi, model imputedCostModel) (
lnwire.MilliSatoshi, error) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This function signature exceeds the 80-character line limit, violating the style guide.1 Please wrap the arguments to new lines.

Style Guide References

Suggested change
func (m *ImputedCostManager) calcShardLimit(paymentHash lntypes.Hash, shardAmt,
costLimit lnwire.MilliSatoshi, model imputedCostModel) (
lnwire.MilliSatoshi, error) {
func (m *ImputedCostManager) calcShardLimit(paymentHash lntypes.Hash,
shardAmt, costLimit lnwire.MilliSatoshi, model imputedCostModel) (
lnwire.MilliSatoshi, error) {

Footnotes

  1. The style guide provides rules for wrapping long function definitions to adhere to the 80-character line limit. (link)

@feelancer21 feelancer21 marked this pull request as draft July 26, 2025 07:43
@feelancer21 feelancer21 force-pushed the imputed-costs-v2 branch 7 times, most recently from 61db23d to b8489a1 Compare July 29, 2025 22:52
- Add experimental imputed costs API to router service with three new
  RPCs: XImportImputedCosts, XQueryImputedCosts, XDeleteImputedCosts.
- Introduces messages for ImputedCostNamespace, ImputedCostPair and
  ImputedCostParameters with support for success-based and attempt-based
  cost calculations.
- Adds imputed_cost_restrictions field to SendPaymentRequest and
  QueryRoutesRequest for total routing cost limits.
- Compiling of the protos
- Update of router.yaml
We added the ImputedCostManager to SessionSource and paymentSession and
fixed the existing utests.
`queryicm` queries the internal state of the imputed cost manager.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants