UNPKG

balanceofsatoshis

Version:
160 lines (129 loc) 4.88 kB
const asyncAuto = require('async/auto'); const {enforceForwardRequestRules} = require('ln-sync'); const {returnResult} = require('asyncjs-util'); const disableAllForwards = 0; const hoursAsSeconds = hours => hours * 60 * 60; const {isArray} = Array; const isEdge = n => !!n && /^[0-9A-F]{66}\/[0-9A-F]{66}$/i.test(n); const splitEdge = n => n.split('/'); /** Limit forwarding requests { lnd: (await lndForNode(logger, options.node)).lnd, logger: <Winston Logger Object> [is_disabling_all_forwards]: <All Forwards Are Disabled Bool> [max_hours_since_last_block]: <Maximum Hours Since Last Block Number> [max_new_pending_per_hour]: <Maximum Outstanding New HTLCs Per Hour Number> [min_channel_confirmations]: <Minimum Required Channel Confs Number> only_allow: [<In Public Key / Out Public Key String>] only_disallow: [<In Public Key / Out Public Key String>] stop_channels: [<Channel Id to Stop Traffic On String>] } @returns via cbk or Promise */ module.exports = (args, cbk) => { return new Promise((resolve, reject) => { return asyncAuto({ // Check arguments validate: cbk => { if (!isArray(args.only_allow)) { return cbk([400, 'ExpectedOnlyAllowArrayToLimitForwarding']); } if (!isArray(args.only_disallow)) { return cbk([400, 'ExpectedOnlyDisallowArrayToLimitForwarding']); } if (!!args.only_allow.length && !!args.only_disallow.length) { return cbk([400, 'ExpectedEitherAllowOrDisallowPublicKeyPairs']); } if (!!args.only_allow.filter(n => !isEdge(n)).length) { return cbk([400, 'ExpectedOnlyAllowAsPublicKeyPairs']); } if (!!args.only_disallow.filter(n => !isEdge(n)).length) { return cbk([400, 'ExpectedOnlyDisallowAsPublicKeyPairs']); } if (!args.logger) { return cbk([400, 'ExpectedWinstonLoggerToLimitForwarding']); } if (!args.lnd) { return cbk([400, 'ExpectedAuthenticatedLndToLimitForwarding']); } if (!isArray(args.stop_channels)) { return cbk([400, 'ExpectedStopChannelsArrayToLimitForwarding']); } return cbk(); }, // Max pending per hour maxPendingPerHour: ['validate', ({}, cbk) => { if (!!args.is_disabling_all_forwards) { return cbk(null, disableAllForwards); } if (!!args.max_new_pending_per_hour) { return cbk(null, args.max_new_pending_per_hour); } return cbk(); }], // Max seconds allowed since the last block maxSecondsSinceLastBlock: ['validate', ({}, cbk) => { if (!args.max_hours_since_last_block) { return cbk(); } return cbk(null, hoursAsSeconds(args.max_hours_since_last_block)); }], // Only allow pairs onlyAllow: ['validate', ({}, cbk) => { if (!args.only_allow.length) { return cbk(); } const allow = args.only_allow.map(splitEdge).map(([inKey, outKey]) => { return {inbound_peer: inKey, outbound_peer: outKey}; }); return cbk(null, allow); }], // Only disallow pairs onlyDisallow: ['validate', ({}, cbk) => { // Exit early when there is no deny list if (!args.only_disallow.length) { return cbk(); } const edges = args.only_disallow.map(splitEdge); const disallow = edges.map(([inKey, outKey]) => { return {inbound_peer: inKey, outbound_peer: outKey}; }); return cbk(null, disallow); }], // Limit forward requests limit: [ 'maxPendingPerHour', 'maxSecondsSinceLastBlock', 'onlyAllow', 'onlyDisallow', ({ maxPendingPerHour, maxSecondsSinceLastBlock, onlyAllow, onlyDisallow, }, cbk) => { args.logger.info({limiting_forwards: true}); const sub = enforceForwardRequestRules({ lnd: args.lnd, max_new_pending_per_hour: maxPendingPerHour, max_seconds_since_last_block: maxSecondsSinceLastBlock, min_activation_age: args.min_channel_confirmations || undefined, only_allow: onlyAllow, only_disallow: onlyDisallow, stop_channels: args.stop_channels.length ? args.stop_channels : null, }); sub.on('error', err => { return cbk([503, 'UnexpectedErrorLimitingForwarding', {err}]); }); sub.on('rejected', async rejected => { const forward = `${rejected.in_channel}${rejected.out_channel}`; const rejection = `${rejected.reject_reason} ${forward}`; return args.logger.info({rejection}); }); }], }, returnResult({reject, resolve}, cbk)); }); };