Skip to content

Commit

Permalink
use AMP payments
Browse files Browse the repository at this point in the history
  • Loading branch information
antonilol committed Sep 8, 2022
1 parent d3434e8 commit 4d133b4
Show file tree
Hide file tree
Showing 9 changed files with 234 additions and 85 deletions.
56 changes: 32 additions & 24 deletions .github/workflows/integration_test.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
name: Integration Test
on:
name: Integration Tests
on:
pull_request:
branches:
- master

jobs:
build:
runs-on: ubuntu-18.04
integration-test:
runs-on: ubuntu-18.04
strategy:
fail-fast: false
matrix:
test-name: ['boostPayment', 'botCreation', 'chatPayment', 'cleanup', 'clearAllChats', 'clearAllContacts', 'contacts', 'images', 'latestTest', 'lsats', 'paidMeet', 'paidTribeImages', 'queryRoutes', 'self', 'sphinxPeople', 'streamPayment', 'tribe', 'tribe3Escrow', 'tribe3Messages', 'tribe3Private', 'tribe3Profile', 'tribeEdit', 'tribeImages', 'messageLength', 'transportToken', 'pinnedMsg', 'hmac', 'socketIO', 'tribeMember']
test-name: [
'boostPayment', 'botCreation', 'chatPayment', 'cleanup', 'clearAllChats',
'clearAllContacts', 'contacts', 'images', 'latestTest', 'lsats', 'paidMeet',
'paidTribeImages', 'queryRoutes', 'self', 'sphinxPeople', 'streamPayment',
'tribe', 'tribe3Escrow', 'tribe3Messages', 'tribe3Private', 'tribe3Profile',
'tribeEdit', 'tribeImages', 'messageLength', 'transportToken', 'pinnedMsg',
'hmac', 'socketIO', 'tribeMember', 'ampMessage'
]
steps:
- name: Enable docker.host.internal for Ubuntu
run: |
Expand All @@ -25,35 +32,36 @@ jobs:
- name: Build Relay
working-directory: ./relay
run: |
npm install && npm run build && docker build -t sphinxlightning/sphinx-relay .
npm install && npm run build && docker build -t sphinxlightning/sphinx-relay .
- name: Checkout stack
run: |
git clone https://github.com/stakwork/sphinx-stack.git stack
- name: give permissions
git clone -b amp https://github.com/antonilol/sphinx-stack.git stack
- name: give permissions
working-directory: ./stack
run: |
chmod 777 ./bitcoind;
chmod 777 -R ./relay;
chmod 777 -R ./lnd;
chmod 777 -R ./proxy;
- name: Turn on Stack
chmod 777 ./bitcoind
chmod 777 -R ./relay
chmod 777 -R ./lnd
chmod 777 -R ./proxy
- name: Turn on Stack
working-directory: ./stack
run: |
GITACTION_ENV=gitactionenv docker-compose -f alts/proxy.yml --project-dir . up -d
GITACTION_ENV=gitactionenv docker-compose -f alts/proxy.yml --project-dir . up -d
- name: Check for NODES.json
working-directory: ./stack
run: |
sleep 240;
sleep 4m
docker-compose ps
docker logs meme.sphinx
docker logs dave.sphinx
docker wait stack_relaysetup_1;
- name: copy file
uses: canastro/copy-file-action@master
with:
source: "stack/relay/NODES.json"
target: "relay/src/tests/configs/nodes.json"
docker logs -f stack_relaysetup_1
docker logs -f stack_lndsetup_1
- name: copy nodes.json
run: |
mkdir relay/src/tests/configs
cp stack/relay/NODES.json relay/src/tests/configs/nodes.json
- name: Run tests
working-directory: ./relay
run: |
npx ava src/tests/controllers/${{matrix.test-name}}.test.ts --verbose --serial --timeout=2m
# run: npx ava src/tests/controllers/${{matrix.test-name}}.test.ts --verbose --serial --timeout=2m
# a script that runs the same test but allows retries when failed + a lot of logs
run: .github/workflows/test.sh ${{matrix.test-name}}
39 changes: 39 additions & 0 deletions .github/workflows/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/bin/bash

delay=10
retries=3

i=0

while true; do
if (npx ava src/tests/controllers/"$1".test.ts --verbose --serial --timeout=2m); then
break
else
((i++))
if [ $i -gt $retries ]; then
echo DEBUG LOGS

echo -e "\n\n== alice chans ==\n\n"
docker exec alice-lnd.sphinx lncli -n regtest listchannels

echo -e "\n\n=== bob chans ===\n\n"
docker exec bob-lnd.sphinx lncli -n regtest --rpcserver=localhost:10010 listchannels

echo -e "\n\n== carol chans ==\n\n"
docker exec carol-lnd.sphinx lncli -n regtest --rpcserver=localhost:10011 listchannels

echo -e "\n\n===== alice =====\n\n"
docker logs alice.sphinx

echo -e "\n\n====== bob ======\n\n"
docker logs bob.sphinx

echo -e "\n\n===== carol =====\n\n"
docker logs carol.sphinx

exit 1
fi
echo Test failed, retrying in "$delay"s "($i/$retries)"
sleep $delay
fi
done
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,4 @@ creds/*
!creds/scheduler_creds
hsm_secret

src/tests/configs/*
src/tests/configs/nodes.json
src/tests/configs/
5 changes: 4 additions & 1 deletion src/grpc/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -357,12 +357,14 @@ export interface KeysendRequest {
final_cltv_delta: number
dest: Buf
dest_custom_records: DestCustomRecords
payment_hash: Buf
payment_hash?: Buf
dest_features: number[]
route_hints?: RouteHint[]
fee_limit?: { [k: string]: number }
fee_limit_sat?: number
timeout_seconds?: number
// to use amp, unset payment_hash and dest_custom_records[`${LND_KEYSEND_KEY}`]
amp?: boolean
}
interface GreenlightHop {
node_id: Buf
Expand Down Expand Up @@ -530,6 +532,7 @@ export interface Invoice {
htlcs: InvoiceHTLC[]
features: { [k: string]: any }
is_keysend: boolean
is_amp: boolean
}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface Payment {
Expand Down
65 changes: 49 additions & 16 deletions src/grpc/lightning.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { Req } from '../types'
const config = loadConfig()
const LND_IP = config.lnd_ip || 'localhost'
// const IS_LND = config.lightning_provider === "LND";
const IS_GREENLIGHT = config.lightning_provider === 'GREENLIGHT'
export const IS_GREENLIGHT = config.lightning_provider === 'GREENLIGHT'

export const LND_KEYSEND_KEY = 5482373484
export const SPHINX_CUSTOM_RECORD_KEY = 133773310
Expand Down Expand Up @@ -289,22 +289,29 @@ export function keysend(
sphinxLogger.info('keysend', logging.Lightning)
return new Promise(async function (resolve, reject) {
try {
const preimage = ByteBuffer.wrap(crypto.randomBytes(32))
const preimage = crypto.randomBytes(32)
const payment_hash = sha.sha256.arrayBuffer(preimage)
const dest_custom_records = {
[`${LND_KEYSEND_KEY}`]: preimage,
}
if (opts.extra_tlv) {
Object.entries(opts.extra_tlv).forEach(([k, v]) => {
dest_custom_records[k] = ByteBuffer.fromUTF8(v)
dest_custom_records[k] = Buffer.from(v, 'utf8')
})
}
// feature bits:
// 9: tlv-onion
// 15: payment-addr
// 30: amp (required)
const keysend_features = [ 9 ]
const amp_features = [ 9, 15, 30 ]
const options: interfaces.KeysendRequest = {
amt: Math.max(opts.amt, constants.min_sat_amount || 3),
final_cltv_delta: 10,
dest: ByteBuffer.fromHex(opts.dest),
dest_custom_records,
payment_hash: sha.sha256.arrayBuffer(preimage.toBuffer()),
dest_features: [9],
payment_hash,
dest_features: keysend_features
}
if (opts.data) {
options.dest_custom_records[`${SPHINX_CUSTOM_RECORD_KEY}`] =
Expand Down Expand Up @@ -350,25 +357,46 @@ export function keysend(
}
})
} else {
// console.log("SEND sendPaymentV2", options)
// new sendPayment (with optional route hints)
delete options.payment_hash
delete dest_custom_records[`${LND_KEYSEND_KEY}`]
options.dest_features = amp_features
options.amp = true

options.fee_limit_sat = FEE_LIMIT_SAT
options.timeout_seconds = 16
const router = await loadRouter()
const call = router.sendPaymentV2(options)
call.on('data', function (payment) {
const state = payment.status || payment.state
const ampState: string = payment.status || payment.state
if (payment.payment_error) {
reject(payment.payment_error)
} else {
if (state === 'IN_FLIGHT') {
// do nothing
} else if (state === 'FAILED_NO_ROUTE') {
reject(payment.failure_reason || payment)
} else if (state === 'FAILED') {
reject(payment.failure_reason || payment)
} else if (state === 'SUCCEEDED') {
if (ampState === 'SUCCEEDED') {
resolve(payment)
} else if (ampState !== 'IN_FLIGHT') {
sphinxLogger.debug(`AMP ${ampState}, trying keysend`, logging.Lightning)
// restore options
options.payment_hash = payment_hash
options.dest_custom_records[`${LND_KEYSEND_KEY}`] = preimage
options.dest_features = keysend_features
delete options.amp
const call = router.sendPaymentV2(options)
call.on('data', function (payment) {
const keysendState: string = payment.status || payment.state
if (payment.payment_error) {
reject(payment.payment_error)
} else {
if (keysendState === 'SUCCEEDED') {
resolve(payment)
} else if (keysendState !== 'IN_FLIGHT') {
sphinxLogger.debug(`AMP ${ampState} and keysend ${keysendState}`, logging.Lightning)
reject(payment.failure_reason || payment)
}
}
})
call.on('error', function (err) {
reject(err)
})
}
}
})
Expand Down Expand Up @@ -859,7 +887,12 @@ export async function complexBalances(
0
)
const spendableBalance = channels.reduce(
(a, chan) => a + Math.max(0, parseInt(chan.local_balance) - parseInt(chan.local_chan_reserve_sat)),
(a, chan) =>
a +
Math.max(
0,
parseInt(chan.local_balance) - parseInt(chan.local_chan_reserve_sat)
),
0
)
const response = await channelBalance(ownerPubkey)
Expand Down
2 changes: 1 addition & 1 deletion src/grpc/subscribe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export function subscribeInvoices(
return
}
// console.log("IS KEYSEND", inv.is_keysend)
if (inv.is_keysend) {
if (inv.is_keysend || inv.is_amp) {
parseKeysendInvoice(inv)
} else {
receiveNonKeysend(inv)
Expand Down
15 changes: 9 additions & 6 deletions src/network/receive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import * as bolt11 from '@boltz/bolt11'
import { loadConfig } from '../utils/config'
import { sphinxLogger, logging } from '../utils/logger'
import { Payload, AdminPayload } from './interfaces'
import * as sha from 'js-sha256'

const config = loadConfig()
/*
Expand Down Expand Up @@ -514,12 +515,14 @@ const hashCache: { [k: string]: boolean } = {}
export async function parseKeysendInvoice(
i: interfaces.Invoice
): Promise<void> {
try {
const hash = i.r_hash.toString('base64')
if (hashCache[hash]) return
hashCache[hash] = true
} catch (e) {
sphinxLogger.error('failed hash cache in parseKeysendInvoice')
if (Lightning.IS_GREENLIGHT) {
try {
const hash = sha.sha256.hex(JSON.stringify(i))
if (hashCache[hash]) return
hashCache[hash] = true
} catch (e) {
sphinxLogger.error('failed hash cache in parseKeysendInvoice')
}
}

const recs = i.htlcs && i.htlcs[0] && i.htlcs[0].custom_records
Expand Down
Loading

0 comments on commit 4d133b4

Please sign in to comment.