Browse Source

Merge pull request #758 from mrfelton/chore/update-lnd-0.5-beta-rc2-60-g1c4bd04c

feat(lnd): update lnd to latest master build
renovate/lint-staged-8.x
JimmyMow 7 years ago
committed by GitHub
parent
commit
0afe3699c9
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 27
      app/lib/lnd/neutrino.js
  2. 85
      app/lib/zap/controller.js
  3. 2
      app/reducers/invoice.js
  4. 2
      package.json
  5. 23
      resources/lnd.conf
  6. 29
      resources/rpc.proto
  7. 15
      test/unit/lnd/neutrino.spec.js

27
app/lib/lnd/neutrino.js

@ -15,7 +15,7 @@ const CHAIN_SYNC_COMPLETE = 'chain-sync-finished'
// Events
const ERROR = 'error'
const CLOSE = 'close'
const EXIT = 'exit'
const WALLET_UNLOCKER_GRPC_ACTIVE = 'wallet-unlocker-grpc-active'
const LIGHTNING_GRPC_ACTIVE = 'lightning-grpc-active'
const GOT_CURRENT_BLOCK_HEIGHT = 'got-current-block-height'
@ -90,11 +90,25 @@ class Neutrino extends EventEmitter {
// neutrinoArgs.push('--neutrino.connect=testnet2-btcd.zaphq.io')
}
mainLog.info(
'Spawning Neutrino process: %s %s',
this.lndConfig.binaryPath,
neutrinoArgs.join(' ')
)
this.process = spawn(this.lndConfig.binaryPath, neutrinoArgs)
.on('error', error => this.emit(ERROR, error))
.on('close', code => {
this.emit(CLOSE, code, this.lastError)
.on('error', error => {
mainLog.debug('Neutrino process received "error" event with error: %s', error)
this.emit(ERROR, error, this.lastError)
})
.on('exit', (code, signal) => {
mainLog.debug(
'Neutrino process received "exit" event with code %s and signal %s',
code,
signal
)
this.process = null
this.emit(EXIT, code, signal, this.lastError)
})
// Listen for when neutrino prints data to stderr.
@ -230,11 +244,10 @@ class Neutrino extends EventEmitter {
/**
* Stop the Lnd process.
*/
kill() {
kill(signalName: string = 'SIGINT') {
if (this.process) {
mainLog.info('Killing Neutrino process...')
this.process.kill()
this.process = null
this.process.kill(signalName)
}
}

85
app/lib/zap/controller.js

@ -288,11 +288,8 @@ class ZapController {
}
}
/**
/**
* Starts the LND node and attach event listeners.
* @param {string} alias Alias to assign to the lnd node.
* @param {boolean} autopilot True if autopilot should be enabled.
* @return {Neutrino} Neutrino instance.
*/
startNeutrino() {
@ -307,12 +304,12 @@ class ZapController {
})
})
this.neutrino.on('close', (code, lastError) => {
mainLog.info(`Lnd process has shut down (code ${code})`)
this.neutrino.on('exit', (code, signal, lastError) => {
mainLog.info(`Lnd process has shut down (code: ${code}, signal: ${signal})`)
if (this.is('running') || this.is('connected')) {
dialog.showMessageBox({
type: 'error',
message: `Lnd has unexpectedly quit: ${lastError}`
message: `Lnd has unexpectedly quit:\n\nError code: ${code}\nExit signal: ${signal}\nLast error: ${lastError}`
})
this.terminate()
}
@ -358,61 +355,45 @@ class ZapController {
*/
async shutdownNeutrino() {
// We only want to shut down LND if we are running it locally.
if (this.lndConfig.type !== 'local') {
if (this.lndConfig.type !== 'local' || !this.neutrino || !this.neutrino.process) {
return Promise.resolve()
}
// Attempt a graceful shutdown if we can.
if (this.lightning && this.lightning.can('terminate')) {
mainLog.info('Shutting down Neutrino...')
return new Promise(resolve => {
// HACK: Sometimes there are errors during the shutdown process that prevent the daeming from shutting down at
// all. If we haven't received notification of the process closing within 10 seconds, kill it.
// See https://github.com/lightningnetwork/lnd/pull/1781
// See https://github.com/lightningnetwork/lnd/pull/1783
const shutdownTimeout = setTimeout(() => {
this.neutrino.removeListener('close', closeHandler)
if (this.neutrino) {
mainLog.warn('Graceful shutdown failed to complete within 10 seconds.')
this.neutrino.kill()
resolve()
}
}, 1000 * 10)
// HACK: The Lightning.stopDaemon` call returns before lnd has actually fully completed the shutdown process
// so we add a listener on the close event so that we can wrap things up once the process has been fully closed
// out.
const closeHandler = function() {
mainLog.info('Neutrino shutdown complete.')
clearTimeout(shutdownTimeout)
mainLog.info('Shutting down Neutrino...')
return new Promise(async resolve => {
// HACK: Sometimes there are errors during the shutdown process that prevent the daeming from shutting down at
// all. If we haven't received notification of the process closing within 10 seconds, kill it.
// See https://github.com/lightningnetwork/lnd/pull/1781
// See https://github.com/lightningnetwork/lnd/pull/1783
const shutdownTimeout = setTimeout(() => {
this.neutrino.removeListener('exit', exitHandler)
if (this.neutrino) {
mainLog.warn('Graceful shutdown failed to complete within 10 seconds.')
this.neutrino.kill('SIGTERM')
resolve()
}
this.neutrino.once('close', closeHandler)
this.lightning
.terminate()
.then(() => mainLog.info('Neutrino Daemon shutdown complete'))
.catch(err => {
mainLog.error('Unable to gracefully shutdown LND: %o', err)
// Kill the process ourselves here to ensure that we don't leave hanging processes.
if (this.neutrino) {
this.neutrino.kill()
resolve()
}
})
})
}
}, 1000 * 10)
const exitHandler = () => {
clearTimeout(shutdownTimeout)
resolve()
}
this.neutrino.once('exit', exitHandler)
// The Lightning service is only active after the wallet has been unlocked and a gRPC connection has been
// established. In this case, kill the Neutrino process to ensure that we don't leave hanging process.
// FIXME: This currencly doesn't do a graceful shutdown as LND does not properly handle SIGTERM.
// See https://github.com/lightningnetwork/lnd/issues/1028
else if (this.neutrino) {
// The Lightning service is only active once the wallet has been unlocked and a gRPC connection has been made.
// If it is active, disconnect from it before we terminate neutrino.
if (this.lightning && this.lightning.can('terminate')) {
await this.lightning.disconnect()
}
// Kill the Neutrino process (sends SIGINT to Neutrino process)
this.neutrino.kill()
}
}).then(() => mainLog.info('Neutrino shutdown complete'))
}
/**
* Start or connect to lnd process after onboarding has been completed by the app.
*/
finishOnboarding(options: onboardingOptions) {
mainLog.info('Finishing onboarding')
// Save the lnd config options that we got from the renderer.

2
app/reducers/invoice.js

@ -40,7 +40,7 @@ export const UPDATE_INVOICE = 'UPDATE_INVOICE'
// Decorate invoice object with custom/computed properties.
const decorateInvoice = invoice => {
invoice.finalAmount = invoice.amt_paid ? invoice.amt_paid : invoice.value
invoice.finalAmount = invoice.amt_paid_sat ? invoice.amt_paid_sat : invoice.value
return invoice
}

2
package.json

@ -42,7 +42,7 @@
"config": {
"style_paths": "app/styles/*.scss app/components/**/*.scss",
"lnd-binary": {
"binaryVersion": "0.5-beta-rc2-41-g4dd4f7cf",
"binaryVersion": "0.5-beta-6-g48d016bc",
"binarySite": "https://github.com/LN-Zap/lnd/releases/download"
}
},

23
resources/lnd.conf

@ -42,15 +42,23 @@
; Path to write the admin macaroon for lnd's RPC and REST services if it
; doesn't exist. This can be set if one wishes to store the admin macaroon in a
; distinct location. By default, it is stored within lnd's main home directory.
; Applications that are able to read this file, gains admin macaroon access
; adminmacaroonpath=~/.lnd/admin.macaroon
; distinct location. By default, it is stored within lnd's network directory.
; Applications that are able to read this file, gain admin macaroon access.
; adminmacaroonpath=~/.lnd/data/chain/bitcoin/simnet/admin.macaroon
; Path to write the read-only macaroon for lnd's RPC and REST services if it
; doesn't exist. This can be set if one wishes to store the read-only macaroon
; in a distinct location. The read only macaroon allows users which can read
; the file to access RPCs which don't modify the state of the daemon.
; readonlymacaroonpath=~/.lnd/readonly.macaroon
; the file to access RPCs which don't modify the state of the daemon. By
; default, it is stored within lnd's network directory.
; readonlymacaroonpath=~/.lnd/data/chain/bitcoin/simnet/readonly.macaroon
; Path to write the invoice macaroon for lnd's RPC and REST services if it
; doesn't exist. This can be set if one wishes to store the invoice macaroon in
; a distinct location. By default, it is stored within lnd's network directory.
; The invoice macaroon allows users which can read the file to gain read and
; write access to all invoice related RPCs.
; invoicemacaroonpath=~/.lnd/data/chain/bitcoin/simnet/invoice.macaroon
; Specify the interfaces to listen on for p2p connections. One listen
@ -128,11 +136,6 @@ debuglevel=debug
; network.
; nobootstrap=1
; If set, your wallet will be encrypted with the default passphrase. This isn't
; recommend, as if an attacker gains access to your wallet file, they'll be able
; to decrypt it. This value is ONLY to be used in testing environments.
; noencryptwallet=1
; The alias your node will use, which can be up to 32 UTF-8 characters in
; length.
; alias=My Lightning ☇

29
resources/rpc.proto

@ -1,4 +1,4 @@
// Imported from https://github.com/lightningnetwork/lnd/blob/baee07ef480c15a731e0c87dc98d27269c5a80fa/lnrpc/rpc.proto
// Imported from https://github.com/lightningnetwork/lnd/blob/48d016bc78e9f338742b10d936e52e7655fd8770/lnrpc/rpc.proto
syntax = "proto3";
// import "google/api/annotations.proto";
@ -1670,15 +1670,28 @@ message Invoice {
*/
uint64 settle_index = 17 [json_name = "settle_index"];
/// Deprecated, use amt_paid_sat or amt_paid_msat.
int64 amt_paid = 18 [json_name = "amt_paid", deprecated = true];
/**
The amount that was accepted for this invoice, in satoshis. This will ONLY
be set if this invoice has been settled. We provide this field as if the
invoice was created with a zero value, then we need to record what amount
was ultimately accepted. Additionally, it's possible that the sender paid
MORE that was specified in the original invoice. So we'll record that here
as well.
*/
int64 amt_paid_sat = 19 [json_name = "amt_paid_sat"];
/**
The amount that was accepted for this invoice. This will ONLY be set if
this invoice has been settled. We provide this field as if the invoice was
created with a zero value, then we need to record what amount was
ultimately accepted. Additionally, it's possible that the sender paid MORE
that was specified in the original invoice. So we'll record that here as
well.
The amount that was accepted for this invoice, in millisatoshis. This will
ONLY be set if this invoice has been settled. We provide this field as if
the invoice was created with a zero value, then we need to record what
amount was ultimately accepted. Additionally, it's possible that the sender
paid MORE that was specified in the original invoice. So we'll record that
here as well.
*/
int64 amt_paid = 18 [json_name = "amt_paid"];
int64 amt_paid_msat = 20 [json_name = "amt_paid_msat"];
}
message AddInvoiceResponse {
bytes r_hash = 1 [json_name = "r_hash"];

15
test/unit/lnd/neutrino.spec.js

@ -200,19 +200,4 @@ describe('Neutrino', function() {
})
})
})
describe('.kill', () => {
describe('called when neutrino is already running', () => {
beforeEach(() => {
this.neutrino = new Neutrino(new LndConfig())
this.neutrino.process = {
kill: jest.fn()
}
this.neutrino.kill()
})
it('should kill the neutrino process', () => {
expect(this.neutrino.process).toBeNull()
})
})
})
})

Loading…
Cancel
Save