This repository has been archived by the owner on Nov 17, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 216
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(wallet): use sendpaymentv2 for probing if available
- Loading branch information
Showing
3 changed files
with
107 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -87,6 +87,91 @@ async function probePayment(payload) { | |
}) | ||
} | ||
|
||
/** | ||
* probePaymentV2 - Call lnd grpc sendPayment method with a fake payment hash in order to probe for a route. | ||
* | ||
* @param {object} payload Payload | ||
* @returns {Promise} The route route when state is SUCCEEDED | ||
*/ | ||
async function probePaymentV2(payload) { | ||
// Use a payload that has the payment hash set to some random bytes. | ||
// This will cause the payment to fail at the final destination. | ||
payload.paymentHash = new Uint8Array(generatePreimage()) | ||
|
||
logGrpcCmd('Router.probePaymentV2', payload) | ||
|
||
let result | ||
let error | ||
|
||
const decorateError = e => { | ||
e.details = result | ||
return e | ||
} | ||
|
||
return new Promise((resolve, reject) => { | ||
grpcLog.time('probePayment') | ||
const call = this.service.sendPaymentV2(payload) | ||
let route | ||
|
||
call.on('data', data => { | ||
grpcLog.debug('PROBE DATA :%o', data) | ||
|
||
switch (data.status) { | ||
case 'IN_FLIGHT': | ||
grpcLog.info('PROBE IN_FLIGHT...') | ||
break | ||
|
||
case 'FAILED': | ||
if (data.failureReason !== 'FAILURE_REASON_INCORRECT_PAYMENT_DETAILS') { | ||
grpcLog.warn('PROBE FAILED: %o', data) | ||
error = new Error(data.status) | ||
break | ||
} | ||
|
||
grpcLog.info('PROBE SUCCESS: %o', data) | ||
// Prior to lnd v0.10.0 sendPayment would return a single route under the `route` key. | ||
route = data.route || data.htlcs[0].route | ||
// FIXME: For some reason the customRecords key is corrupt in the grpc response object. | ||
// For now, assume that if a custom_record key is set that it is a keysend record and fix it accordingly. | ||
route.hops = route.hops.map(hop => { | ||
Object.keys(hop.customRecords).forEach(key => { | ||
hop.customRecords[KEYSEND_PREIMAGE_TYPE] = hop.customRecords[key] | ||
delete hop.customRecords[key] | ||
}) | ||
return hop | ||
}) | ||
result = route | ||
break | ||
|
||
default: | ||
grpcLog.warn('PROBE FAILED: %o', data) | ||
error = new Error(data.status) | ||
} | ||
}) | ||
|
||
call.on('status', status => { | ||
grpcLog.info('PROBE STATUS :%o', status) | ||
}) | ||
|
||
call.on('error', e => { | ||
grpcLog.warn('PROBE ERROR :%o', e) | ||
error = new Error(e.details || e.message) | ||
}) | ||
|
||
call.on('end', () => { | ||
grpcLog.timeEnd('probePaymentV2') | ||
grpcLog.info('PROBE END') | ||
if (error) { | ||
return reject(decorateError(error)) | ||
} | ||
if (!result) { | ||
return reject(decorateError(new Error('TERMINATED_EARLY'))) | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
mrfelton
Author
Member
|
||
} | ||
return resolve(result) | ||
}) | ||
}) | ||
} | ||
|
||
/** | ||
* sendPayment - Call lnd grpc sendPayment method. | ||
* | ||
|
@@ -224,6 +309,7 @@ async function sendPaymentV2(payload = {}) { | |
|
||
export default { | ||
probePayment, | ||
probePaymentV2, | ||
sendPayment, | ||
sendPaymentV2, | ||
} |
Looks like in this case error will be decorated with empty result. Is this desirable?