balanceofsatoshis
Version:
Lightning balance CLI
138 lines (116 loc) • 3.86 kB
JavaScript
const asyncAuto = require('async/auto');
const {decodeFirst} = require('cbor');
const {diffieHellmanComputeSecret} = require('ln-service');
const {getIdentity} = require('ln-service');
const {getNode} = require('ln-service');
const {returnResult} = require('asyncjs-util');
const decryptWithSecret = require('./decrypt_with_secret');
const hexAsBuf = hex => Buffer.from(hex, 'hex');
const {isArray} = Array;
/** Decrypt data from node
{
encrypted: <Encrypted Data Hex String>
lnd: <Authenticated LND gRPC API Object>
}
@returns via cbk or Promise
{
message: <Message Object>
with_alias: <With Node Public Key Hex String>
with_public_key: <With Public Key Hex String>
}
*/
module.exports = ({encrypted, lnd}, cbk) => {
return new Promise((resolve, reject) => {
return asyncAuto({
// Check arguments
validate: cbk => {
if (!encrypted) {
return cbk([400, 'ExpectedEncryptedPayloadToDecryptData']);
}
if (!lnd) {
return cbk([400, 'ExpectedLndToDecryptData']);
}
return cbk();
},
// Decode encrypted CBOR
decode: ['validate', ({}, cbk) => {
return decodeFirst(encrypted, (err, details) => {
if (!!err) {
return cbk([400, 'ExpectedCborEncodedEncryptedData', {err}]);
}
if (!details) {
return cbk([400, 'ExpectedDecodedDetailsToDecryptWithNode']);
}
if (!details.settings) {
return cbk([400, 'ExpectedEncryptionSettingsToDecryptWithNode']);
}
if (!isArray(details.settings.with)) {
return cbk([400, 'ExpectedWithNodesPublicKeyToDecrypt']);
}
return cbk(null, details);
});
}],
// Get node public key
getPublicKey: ['decode', ({decode}, cbk) => getIdentity({lnd}, cbk)],
// Determine the foreign key if any
foreignKey: ['decode', 'getPublicKey', ({decode, getPublicKey}, cbk) => {
const keys = decode.settings.with;
const foreignKey = keys.find(n => n !== getPublicKey.public_key);
return cbk(null, foreignKey || getPublicKey.public_key);
}],
// Get details about the node
getNode: ['foreignKey', ({foreignKey}, cbk) => {
return getNode({
lnd,
is_omitting_channels: true,
public_key: foreignKey,
},
(err, res) => {
if (!!err) {
return cbk(null, {public_key: foreignKey});
}
return cbk(null, {alias: res.alias, public_key: foreignKey});
});
}],
// Derive the shared secret
getSecret: ['foreignKey', ({foreignKey}, cbk) => {
return diffieHellmanComputeSecret({
lnd,
partner_public_key: foreignKey,
},
cbk);
}],
// Decrypt the data
decrypt: ['decode', 'getSecret', ({decode, getSecret}, cbk) => {
return decryptWithSecret({
encrypted: Buffer.from(decode.encrypted, 'hex'),
iv: decode.iv,
salt: decode.salt,
secret: getSecret.secret,
settings: {
algorithm: decode.settings.algorithm,
derivation: decode.settings.derivation,
digest: decode.settings.digest,
key_length: decode.settings.key_length,
},
tag: decode.tag,
},
cbk);
}],
// Cleartext
clear: [
'decode',
'decrypt',
'getNode',
({decode, decrypt, getNode}, cbk) =>
{
return cbk(null, {
with_alias: getNode.alias || undefined,
with_public_key: getNode.public_key,
message: hexAsBuf(decrypt.plain).toString(decode.settings.encoding),
});
}],
},
returnResult({reject, resolve, of: 'clear'}, cbk));
});
};