-
Notifications
You must be signed in to change notification settings - Fork 169
Enable macaroons #552
Enable macaroons #552
Changes from all commits
261ba48
eef45c5
fe57bbf
62d482a
4a3409a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,23 +32,27 @@ async function getCredentials(lndSettingsDir) { | |
return grpc.credentials.createSsl(lndCert); | ||
} | ||
|
||
function getMetadata(lndSettingsDir) { | ||
const metadata = new grpc.Metadata(); | ||
const macaroonPath = path.join(lndSettingsDir, 'admin.macaroon'); | ||
const macaroonHex = fs.readFileSync(macaroonPath).toString('hex'); | ||
metadata.add('macaroon', macaroonHex); | ||
return metadata; | ||
function getMacaroonCreds(lndSettingsDir, network) { | ||
return grpc.credentials.createFromMetadataGenerator((args, callback) => { | ||
const metadata = new grpc.Metadata(); | ||
const macaroonPath = path.join( | ||
lndSettingsDir, | ||
`data/chain/bitcoin/${network}/admin.macaroon` | ||
); | ||
const macaroonHex = fs.readFileSync(macaroonPath).toString('hex'); | ||
metadata.add('macaroon', macaroonHex); | ||
callback(null, metadata); | ||
}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How does this work with return if it's asynchronous? Don't we need to wait for the callback to set the metadata? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In order to combine the ssl credentials with the macaroon metadata, we need to turn the metadata into a
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok. Thanks for the explanation. |
||
} | ||
|
||
module.exports.init = async function({ | ||
ipcMain, | ||
lndPort, | ||
lndSettingsDir, | ||
macaroonsEnabled, | ||
network, | ||
}) { | ||
let credentials; | ||
let protoPath; | ||
let metadata; | ||
let lnrpc; | ||
let unlocker; | ||
let lnd; | ||
|
@@ -57,9 +61,6 @@ module.exports.init = async function({ | |
credentials = await getCredentials(lndSettingsDir); | ||
protoPath = path.join(__dirname, '..', 'assets', 'rpc.proto'); | ||
lnrpc = grpc.load(protoPath).lnrpc; | ||
if (macaroonsEnabled) { | ||
metadata = getMetadata(lndSettingsDir); | ||
} | ||
unlocker = new lnrpc.WalletUnlocker(`localhost:${lndPort}`, credentials); | ||
grpc.waitForClientReady(unlocker, Infinity, err => { | ||
event.sender.send('unlockReady', { err }); | ||
|
@@ -72,6 +73,11 @@ module.exports.init = async function({ | |
}); | ||
|
||
ipcMain.on('lndInit', event => { | ||
const macaroonCreds = getMacaroonCreds(lndSettingsDir, network); | ||
credentials = grpc.credentials.combineChannelCredentials( | ||
credentials, | ||
macaroonCreds | ||
); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So the locker doesn't need macaroons? Only the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the wallet hasn't been initialized, the macaroons don't exist yet. The wallet creation process involves creating the macaroons :) |
||
lnd = new lnrpc.Lightning(`localhost:${lndPort}`, credentials); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So we don't need to pass the metadata in each api call because we inject the credentials here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, thought it simplified the code a bit to not have to remember to pass in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we stayed with passing in metadata each time, we'd also have to get the macaroons to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok great 👍 |
||
grpc.waitForClientReady(lnd, Infinity, err => { | ||
event.sender.send('lndReady', { err }); | ||
|
@@ -88,33 +94,21 @@ module.exports.init = async function({ | |
const handleResponse = (err, response) => { | ||
event.sender.send(`unlockResponse_${method}`, { err, response }); | ||
}; | ||
if (metadata) { | ||
unlocker[method](body, metadata, { deadline }, handleResponse); | ||
} else { | ||
unlocker[method](body, { deadline }, handleResponse); | ||
} | ||
unlocker[method](body, { deadline }, handleResponse); | ||
}); | ||
|
||
ipcMain.on('lndRequest', (event, { method, body }) => { | ||
const deadline = new Date(new Date().getTime() + GRPC_TIMEOUT); | ||
const handleResponse = (err, response) => { | ||
event.sender.send(`lndResponse_${method}`, { err, response }); | ||
}; | ||
if (metadata) { | ||
lnd[method](body, metadata, { deadline }, handleResponse); | ||
} else { | ||
lnd[method](body, { deadline }, handleResponse); | ||
} | ||
lnd[method](body, { deadline }, handleResponse); | ||
}); | ||
|
||
const streams = {}; | ||
ipcMain.on('lndStreamRequest', (event, { method, body }) => { | ||
let stream; | ||
if (metadata) { | ||
stream = lnd[method](metadata, body); | ||
} else { | ||
stream = lnd[method](body); | ||
} | ||
stream = lnd[method](body); | ||
const send = res => event.sender.send(`lndStreamEvent_${method}`, res); | ||
stream.on('data', data => send({ event: 'data', data })); | ||
stream.on('end', () => send({ event: 'end' })); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,7 +9,7 @@ module.exports.RATE_DELAY = 15 * 60 * 1000; | |
|
||
module.exports.LND_PORT = 10009; | ||
module.exports.LND_PEER_PORT = 10019; | ||
module.exports.MACAROONS_ENABLED = false; | ||
module.exports.NETWORK = 'testnet'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What if we're in dev mode? Then the app will start with |
||
module.exports.BTCD_MINING_ADDRESS = 'rfu4i1Mo2NF7TQsN9bMVLFSojSzcyQCEH5'; | ||
|
||
const prefixName = 'lightning'; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice update to the docs 👍