mirror of
https://github.com/alexbosworth/balanceofsatoshis.git
synced 2026-08-13 12:33:37 +02:00
add joint capacity to formula variables
This commit is contained in:
parent
40c808cfb7
commit
9c31a9bfa9
9 changed files with 70 additions and 38 deletions
|
|
@ -1,5 +1,10 @@
|
|||
# Versions
|
||||
|
||||
## 15.4.0
|
||||
|
||||
- `inbound-channel-rules`: Add `JOINT_PUBLIC_CAPACITY` for rules based on
|
||||
existing joint capacity
|
||||
|
||||
## 15.3.0
|
||||
|
||||
- `inbound-channel-rules`: Add support for `--stop` to stop forwards on channel
|
||||
|
|
|
|||
70
bos
70
bos
|
|
@ -877,6 +877,7 @@ prog
|
|||
.command('inbound-channel-rules', 'Enforce rules for inbound channels')
|
||||
.help('Rules should be written evaluating to TRUE to accept a channel')
|
||||
.help('Example rule: --rule "CAPACITY > 100000"')
|
||||
.help('You can use multiple --rule flags to enforce multiple rules')
|
||||
.help('Multiple --coop-close-address supported, will cycle through them')
|
||||
.help('Avoid requiring Blockchain confirmations using --trust-funding-from')
|
||||
.help('For formulas: CAPACITIES are the sizes of the peer public channels')
|
||||
|
|
@ -884,6 +885,7 @@ prog
|
|||
.help('For formulas: CHANNEL_AGES are the block ages of public channels')
|
||||
.help('For formulas: CLEARNET is when peer advertises a clearnet address')
|
||||
.help('For formulas: FEE_RATES are the outbound fee rates for the peer')
|
||||
.help('For formulas: JOINT_PUBLIC_CAPACITY is graph capacity with the peer')
|
||||
.help('For formulas: LOCAL_BALANCE is the gifted amount from the peer')
|
||||
.help('For formulas: M is 1,000,000 - use like CAPACITY > 10*M')
|
||||
.help('For formulas: OBSOLETE is chan type, like NOT(OBSOLETE)')
|
||||
|
|
@ -914,40 +916,6 @@ prog
|
|||
});
|
||||
})
|
||||
|
||||
// Intercept forwarding requests, enforce requirements on acceptance
|
||||
.command('limit-forwarding', 'Enforce rules for routing payments')
|
||||
.help(`--deny option can be repeated for multiple denied from/to paths`)
|
||||
.help('Setting --only-allow will disable all forwards except only allowed')
|
||||
.help('--only-allow option can be repeated for multiple forwards')
|
||||
.help('--stop can be repeated for multiple channels')
|
||||
.option('--deny <pair>', 'disable all forwards fromKey/toKey', REPEATABLE)
|
||||
.option('--disable-forwards', 'Disable all forwards')
|
||||
.option('--max-hours-since-last-block <h>', 'Require fresh blocks', INT, 5)
|
||||
.option('--max-new-pending-per-hour <h>', 'Limit held HTLCs', INT)
|
||||
.option('--min-channel-confirmations <confs>', 'Minimum channel confs', INT)
|
||||
.option('--node <node_name>', 'Saved node to enforce rules on')
|
||||
.option('--only-allow <pair>', 'only forward fromKey/toKey', REPEATABLE)
|
||||
.option('--stop <channel>', 'Stop new forwards on channel', REPEATABLE)
|
||||
.action((args, options, logger) => {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
return await peers.limitForwarding({
|
||||
logger,
|
||||
is_disabling_all_forwards: options.disableForwards || undefined,
|
||||
lnd: (await lndForNode(logger, options.node)).lnd,
|
||||
max_hours_since_last_block: options.maxHoursSinceLastBlock,
|
||||
max_new_pending_per_hour: options.maxNewPendingPerHour,
|
||||
min_channel_confirmations: options.minChannelConfirmations,
|
||||
only_allow: flatten([options.onlyAllow].filter(n => !!n)),
|
||||
only_disallow: flatten([options.deny].filter(n => !!n)),
|
||||
stop_channels: flatten([options.stop].filter(n => !!n)),
|
||||
});
|
||||
} catch (err) {
|
||||
return logger.error({err}) && reject();
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
// Get inbound liquidity information: available inbound off-chain tokens
|
||||
.command('inbound-liquidity', 'Get inbound liquidity size')
|
||||
.option('--above <tokens>', 'Return amount above watermark', INT)
|
||||
|
|
@ -1138,6 +1106,40 @@ prog
|
|||
});
|
||||
})
|
||||
|
||||
// Intercept forwarding requests, enforce requirements on acceptance
|
||||
.command('limit-forwarding', 'Enforce rules for routing payments')
|
||||
.help(`--deny option can be repeated for multiple denied from/to paths`)
|
||||
.help('Setting --only-allow will disable all forwards except only allowed')
|
||||
.help('--only-allow option can be repeated for multiple forwards')
|
||||
.help('--stop can be repeated for multiple channels')
|
||||
.option('--deny <pair>', 'disable all forwards fromKey/toKey', REPEATABLE)
|
||||
.option('--disable-forwards', 'Disable all forwards')
|
||||
.option('--max-hours-since-last-block <h>', 'Require fresh blocks', INT, 5)
|
||||
.option('--max-new-pending-per-hour <h>', 'Limit held HTLCs', INT)
|
||||
.option('--min-channel-confirmations <confs>', 'Minimum channel confs', INT)
|
||||
.option('--node <node_name>', 'Saved node to enforce rules on')
|
||||
.option('--only-allow <pair>', 'only forward fromKey/toKey', REPEATABLE)
|
||||
.option('--stop <channel>', 'Stop new forwards on channel', REPEATABLE)
|
||||
.action((args, options, logger) => {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
return await peers.limitForwarding({
|
||||
logger,
|
||||
is_disabling_all_forwards: options.disableForwards || undefined,
|
||||
lnd: (await lndForNode(logger, options.node)).lnd,
|
||||
max_hours_since_last_block: options.maxHoursSinceLastBlock,
|
||||
max_new_pending_per_hour: options.maxNewPendingPerHour,
|
||||
min_channel_confirmations: options.minChannelConfirmations,
|
||||
only_allow: flatten([options.onlyAllow].filter(n => !!n)),
|
||||
only_disallow: flatten([options.deny].filter(n => !!n)),
|
||||
stop_channels: flatten([options.stop].filter(n => !!n)),
|
||||
});
|
||||
} catch (err) {
|
||||
return logger.error({err}) && reject();
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
// Get the price for liquidity
|
||||
.command('liquidity-cost', 'Get the price of liquidity')
|
||||
.visible(false)
|
||||
|
|
|
|||
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "balanceofsatoshis",
|
||||
"version": "15.3.0",
|
||||
"version": "15.4.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "balanceofsatoshis",
|
||||
"version": "15.3.0",
|
||||
"version": "15.4.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@alexbosworth/caporal": "1.4.4",
|
||||
|
|
|
|||
|
|
@ -83,5 +83,5 @@
|
|||
"postpublish": "docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t alexbosworth/balanceofsatoshis -t alexbosworth/balanceofsatoshis:$npm_package_version --push .",
|
||||
"test": "tap --branches=1 --functions=1 --lines=1 --statements=1 -t 60 test/arrays/*.js test/balances/*.js test/chain/*.js test/display/*.js test/encryption/*.js test/lnd/*.js test/network/*.js test/nodes/*.js test/peers/*.js test/responses/*.js test/routing/*.js test/services/*.js test/swaps/*.js test/tags/*.js test/telegram/*.js test/wallets/*.js"
|
||||
},
|
||||
"version": "15.3.0"
|
||||
"version": "15.4.0"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,11 +10,13 @@ const isClear = sockets => !!sockets.find(n => !!isIP(n.socket.split(':')[0]));
|
|||
const isObsolete = n => !!n && n.startsWith('original');
|
||||
const isOnion = sockets => !!sockets.find(n => /onion/.test(n.socket));
|
||||
const openRequestViolation = require('./open_request_violation');
|
||||
const sumOf = arr => arr.reduce((sum, n) => sum + n, 0);
|
||||
|
||||
/** Detect an open request rule violation
|
||||
|
||||
{
|
||||
capacity: <Channel Capacity Tokens Number>
|
||||
id: <Identity Public Key Hex String>
|
||||
[is_private]: <Channel Request Is For Private Channel Bool>
|
||||
lnd: <Authenticated LND API Object>
|
||||
local_balance: <Local Channel Balance Tokens Number>
|
||||
|
|
@ -37,6 +39,10 @@ module.exports = (args, cbk) => {
|
|||
return cbk([400, 'ExpectedChannelCapacityToDetectRuleViolation']);
|
||||
}
|
||||
|
||||
if (!args.id) {
|
||||
return cbk([400, 'ExpectedIdentityPublicKeyToDetectRuleViolation']);
|
||||
}
|
||||
|
||||
if (!args.lnd) {
|
||||
return cbk([400, 'ExpectedLndToDetectOpenChannelRuleViolation']);
|
||||
}
|
||||
|
|
@ -125,6 +131,11 @@ module.exports = (args, cbk) => {
|
|||
return getHeight.current_block_height - channelHeight;
|
||||
});
|
||||
|
||||
// Filter out channels that already exist
|
||||
const jointChannels = getNodeFees.channels.filter(({policies}) => {
|
||||
return policies.find(n => n.public_key === args.id);
|
||||
});
|
||||
|
||||
try {
|
||||
const {rule} = openRequestViolation({
|
||||
capacities: getNodeFees.channels.map(n => n.capacity),
|
||||
|
|
@ -139,6 +150,7 @@ module.exports = (args, cbk) => {
|
|||
is_obsolete: isObsolete(args.type),
|
||||
is_private: !!args.is_private,
|
||||
is_tor: hasTor,
|
||||
joint_public_capacity: sumOf(jointChannels.map(n => n.capacity)),
|
||||
public_key: args.partner_public_key,
|
||||
rules: args.rules,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
const asyncAuto = require('async/auto');
|
||||
const {getIdentity} = require('ln-service');
|
||||
const {getNetwork} = require('ln-sync');
|
||||
const {returnResult} = require('asyncjs-util');
|
||||
const {subscribeToOpenRequests} = require('ln-service');
|
||||
|
|
@ -65,6 +66,7 @@ module.exports = ({addresses, lnd, logger, reason, rules, trust}, cbk) => {
|
|||
is_obsolete: false,
|
||||
is_private: false,
|
||||
is_tor: false,
|
||||
joint_public_capacity: 1,
|
||||
local_balance: 4,
|
||||
public_key: Buffer.alloc(33, 2).toString('hex'),
|
||||
});
|
||||
|
|
@ -111,8 +113,11 @@ module.exports = ({addresses, lnd, logger, reason, rules, trust}, cbk) => {
|
|||
});
|
||||
}],
|
||||
|
||||
// Get the node key identity
|
||||
getIdentity: ['validate', ({}, cbk) => getIdentity({lnd}, cbk)],
|
||||
|
||||
// Subscribe to open requests
|
||||
subscribe: ['checkAddress', ({}, cbk) => {
|
||||
subscribe: ['checkAddress', 'getIdentity', ({getIdentity}, cbk) => {
|
||||
const sub = subscribeToOpenRequests({lnd});
|
||||
|
||||
// Copy the addresses into a pool
|
||||
|
|
@ -148,6 +153,7 @@ module.exports = ({addresses, lnd, logger, reason, rules, trust}, cbk) => {
|
|||
lnd,
|
||||
rules,
|
||||
capacity: request.capacity,
|
||||
id: getIdentity.public_key,
|
||||
is_private: request.is_private,
|
||||
local_balance: request.local_balance,
|
||||
partner_public_key: peerId,
|
||||
|
|
|
|||
|
|
@ -52,6 +52,10 @@ module.exports = args => {
|
|||
throw new Error('ExpectedChannelPrivateStatusToCheckOpenRequestRules');
|
||||
}
|
||||
|
||||
if (args.joint_public_capacity === undefined) {
|
||||
throw new Error('ExpectedJointPublicCapacityToCheckOpenRequestRules');
|
||||
}
|
||||
|
||||
if (args.local_balance === undefined) {
|
||||
throw new Error('ExpectedLocalBalanceToCheckForOpenRequestViolation');
|
||||
}
|
||||
|
|
@ -75,6 +79,7 @@ module.exports = args => {
|
|||
channel_ages: args.channel_ages,
|
||||
clearnet: args.is_clearnet,
|
||||
fee_rates: args.fee_rates,
|
||||
joint_public_capacity: args.joint_public_capacity,
|
||||
k: 1e3,
|
||||
local_balance: args.local_balance,
|
||||
m: 1e6,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ const {versionInfoResponse} = require('./../fixtures');
|
|||
const makeArgs = overrides => {
|
||||
const args = {
|
||||
capacity: 1,
|
||||
id: Buffer.alloc(33, 2),
|
||||
lnd: {
|
||||
chain: {
|
||||
registerBlockEpochNtfn: ({}) => {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ const makeArgs = overrides => {
|
|||
is_clearnet: true,
|
||||
is_private: true,
|
||||
is_tor: true,
|
||||
joint_public_capacity: 1,
|
||||
local_balance: 7,
|
||||
public_key: Buffer.alloc(33, 3).toString('hex'),
|
||||
rules: ['capacity > 5'],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue