Skip to content

Commit

Permalink
test: add lnd integration tests to fix #38
Browse files Browse the repository at this point in the history
  • Loading branch information
kincaidoneil committed Oct 22, 2019
1 parent 74c7b49 commit b80a04b
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 1 deletion.
4 changes: 3 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ jobs:
command: npm run build
- run:
name: Run tests
command: npm test
command: |
./start-test-env.sh
npm test
- run:
name: Lint files
command: npm run lint
Expand Down
69 changes: 69 additions & 0 deletions src/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import BigNumber from 'bignumber.js'
import { createEngine } from '.'
import { hrtime } from 'process'

const defer = <T>(): [Promise<T>, (val: T) => void] => {
let res: (val: T) => void
const promise = new Promise<T>(resolve => {
res = resolve
})

/* tslint:disable-next-line:no-unnecessary-type-assertion */
return [promise, res!]
}

test('Sends and receives Lightning settlements on local simnet', async () => {
const accountId = 'alice'

// Setup the context so they each send messages to each other
const contextA = {
creditSettlement: jest.fn(),
trySettlement: jest.fn(),
sendMessage: (accountId: string, message: any) =>
engineB.handleMessage(accountId, message)
}

const [amountReceived, gotMoney] = defer<[string, BigNumber]>()

const contextB = {
creditSettlement: (accountId: string, amount: BigNumber) => {
gotMoney([accountId, amount])
},
trySettlement: jest.fn(),
sendMessage: jest.fn()
}

const startAlice = createEngine({
macaroon: process.env.ALICE_ADMIN_MACAROON!,
tlsCert: process.env.ALICE_TLS_CERT!
})(contextA)

const startBob = createEngine({
macaroon: process.env.BOB_ADMIN_MACAROON!,
tlsCert: process.env.BOB_TLS_CERT!,
port: process.env.BOB_GRPC_PORT!
})(contextB)

const engineA = await startAlice
const engineB = await startBob

await engineA.setupAccount(accountId)

const start = hrtime()

// Send settlement for some amount of units
const amountToSettle = new BigNumber(0.0012345)
const amountSettled = await engineA.settle(accountId, amountToSettle)
expect(amountSettled).toStrictEqual(amountToSettle)

await expect(amountReceived).resolves.toStrictEqual([
accountId,
amountSettled
])

console.log('Settlement delay: %dms', hrtime(start)[1] / 1000000)

await Promise.all([engineA.disconnect(), engineB.disconnect()])
}, 20000)

test.todo('Each payment is only credited to one account')
70 changes: 70 additions & 0 deletions start-test-env.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Remove running containers
docker stop alice bob btcd
docker rm alice bob btcd

# Show output and fail fast on errors
# set -x -e

export NETWORK="simnet"

# Download LND v0.8.0
rm -rf ./lnd
git clone https://github.com/lightningnetwork/lnd.git
cd ./lnd
git checkout v0.8.0-beta
cd ./docker

# Create Alice's LND node & wait for RPC server to startup
export ALICE_GRPC_PORT="10009"
docker-compose run --detach --publish $ALICE_GRPC_PORT:10009 --name alice lnd_btc --rpclisten=0.0.0.0:10009 --externalip=alice
sleep 8

export MINING_ADDRESS="$(
# Generate a new backwards-compatible nested p2sh address for Alice
docker exec alice lncli --network="$NETWORK" newaddress np2wkh | \
python -c "import sys, json; print json.load(sys.stdin)['address']"
)"

# Recreate "btcd" node and set Alice's address as mining address
docker-compose up -d btcd

# Generate 400 blocks (> 100 blocks required for coinbase block maturity and > 300 to activate segwit):
docker-compose run btcctl generate 400

# Create Bob's LND node & wait for RPC server to startup
export BOB_GRPC_PORT="10010"
docker-compose run --detach --publish $BOB_GRPC_PORT:10009 --name bob lnd_btc --rpclisten=0.0.0.0:10009 --externalip=bob
sleep 8

BOB_IDENTITY_PUBKEY=$(
# Fetch Bob's identity public key
docker exec bob lncli --network=$NETWORK getinfo | \
python -c "import sys, json; print json.load(sys.stdin)['identity_pubkey']"
)

# Peer Alice's node with Bob's node
docker exec alice lncli --network=$NETWORK connect $BOB_IDENTITY_PUBKEY@bob

# Open Alice -> Bob channel
sleep 10 # Wait for Alice to sync to the chain
docker exec alice lncli --network=$NETWORK openchannel --node_key=$BOB_IDENTITY_PUBKEY --local_amt=10000000

# Include funding transaction in block thereby opening the channel
docker-compose run btcctl generate 3

# Export crednetials to connect over gRPC
export ALICE_ADMIN_MACAROON="$(
docker exec alice cat /root/.lnd/data/chain/bitcoin/simnet/admin.macaroon | base64
)"
export ALICE_TLS_CERT="$(
docker exec alice cat /root/.lnd/tls.cert | base64
)"
export BOB_ADMIN_MACAROON="$(
docker exec bob cat /root/.lnd/data/chain/bitcoin/simnet/admin.macaroon | base64
)"
export BOB_TLS_CERT="$(
docker exec bob cat /root/.lnd/tls.cert | base64
)"

# Return to previous working dir
cd ../..

0 comments on commit b80a04b

Please sign in to comment.