diff --git a/db.go b/db.go index cdb5e36..eb2883c 100644 --- a/db.go +++ b/db.go @@ -24,25 +24,25 @@ func pgConnect() error { return nil } -func paymentInfo(paymentHash []byte) ([]byte, []byte, int64, int64, []byte, uint32, error) { +func paymentInfo(htlcPaymentHash []byte) ([]byte, []byte, []byte, int64, int64, []byte, uint32, error) { var ( - paymentSecret, destination []byte - incomingAmountMsat, outgoingAmountMsat int64 - fundingTxID []byte - fundingTxOutnum pgtype.Int4 + paymentHash, paymentSecret, destination []byte + incomingAmountMsat, outgoingAmountMsat int64 + fundingTxID []byte + fundingTxOutnum pgtype.Int4 ) err := pgxPool.QueryRow(context.Background(), - `SELECT payment_secret, destination, incoming_amount_msat, outgoing_amount_msat, funding_tx_id, funding_tx_outnum + `SELECT payment_hash, payment_secret, destination, incoming_amount_msat, outgoing_amount_msat, funding_tx_id, funding_tx_outnum FROM payments - WHERE payment_hash=$1`, - paymentHash).Scan(&paymentSecret, &destination, &incomingAmountMsat, &outgoingAmountMsat, &fundingTxID, &fundingTxOutnum) + WHERE payment_hash=$1 OR sha256('probing-01:' || payment_hash)=$1`, + htlcPaymentHash).Scan(&paymentHash, &paymentSecret, &destination, &incomingAmountMsat, &outgoingAmountMsat, &fundingTxID, &fundingTxOutnum) if err != nil { if err == pgx.ErrNoRows { err = nil } - return nil, nil, 0, 0, nil, 0, err + return nil, nil, nil, 0, 0, nil, 0, err } - return paymentSecret, destination, incomingAmountMsat, outgoingAmountMsat, fundingTxID, uint32(fundingTxOutnum.Int), nil + return paymentHash, paymentSecret, destination, incomingAmountMsat, outgoingAmountMsat, fundingTxID, uint32(fundingTxOutnum.Int), nil } func setFundingTx(paymentHash, fundingTxID []byte, fundingTxOutnum int) error { diff --git a/go.mod b/go.mod index a8ee50b..f791783 100644 --- a/go.mod +++ b/go.mod @@ -4,16 +4,16 @@ go 1.14 require ( github.com/aws/aws-sdk-go v1.30.20 - github.com/btcsuite/btcd v0.20.1-beta + github.com/btcsuite/btcd v0.20.1-beta.0.20200730232343-1db1b6f8217f github.com/caddyserver/certmagic v0.11.2 github.com/golang/protobuf v1.4.2 github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 github.com/jackc/pgtype v1.4.2 github.com/jackc/pgx/v4 v4.8.1 - github.com/lightningnetwork/lightning-onion v1.0.1 - github.com/lightningnetwork/lnd v0.10.0-beta + github.com/lightningnetwork/lightning-onion v1.0.2-0.20200501022730-3c8c8d0b89ea + github.com/lightningnetwork/lnd v0.11.0-beta golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e google.golang.org/grpc v1.31.0 ) -replace github.com/lightningnetwork/lnd v0.10.0-beta => github.com/breez/lnd v0.10.0-beta.rc6.0.20200727142715-f67a1052c0e0 +replace github.com/lightningnetwork/lnd v0.11.0-beta => github.com/breez/lnd v0.11.0-beta.rc4.0.20201101122458-227226f00b18 diff --git a/intercept.go b/intercept.go index 2c5bb1e..ab629d5 100644 --- a/intercept.go +++ b/intercept.go @@ -3,6 +3,7 @@ package main import ( "bytes" "context" + "encoding/hex" "fmt" "log" "math/big" @@ -32,6 +33,23 @@ func checkPayment(incomingAmountMsat, outgoingAmountMsat int64) error { return nil } +func isConnected(ctx context.Context, client lnrpc.LightningClient, destination []byte) error { + pubKey := hex.EncodeToString(destination) + r, err := client.ListPeers(ctx, &lnrpc.ListPeersRequest{LatestError: true}) + if err != nil { + log.Printf("client.ListPeers() error: %v", err) + return fmt.Errorf("client.ListPeers() error: %w", err) + } + for _, peer := range r.Peers { + if pubKey == peer.PubKey { + log.Printf("destination online: %x", destination) + return nil + } + } + log.Printf("destination offline: %x", destination) + return fmt.Errorf("destination offline") +} + func openChannel(ctx context.Context, client lnrpc.LightningClient, paymentHash, destination []byte, incomingAmountMsat int64) ([]byte, uint32, error) { capacity := incomingAmountMsat/1000 + additionalChannelCapacity channelPoint, err := client.OpenChannelSync(ctx, &lnrpc.OpenChannelRequest{ @@ -104,21 +122,34 @@ func intercept() { request.OnionBlob, ) - paymentSecret, destination, incomingAmountMsat, outgoingAmountMsat, fundingTxID, fundingTxOutnum, err := paymentInfo(request.PaymentHash) + paymentHash, paymentSecret, destination, incomingAmountMsat, outgoingAmountMsat, fundingTxID, fundingTxOutnum, err := paymentInfo(request.PaymentHash) if err != nil { log.Printf("paymentInfo(%x) error: %v", request.PaymentHash, err) } - log.Printf("paymentSecret: %x\ndestination:%x\nincomingAmountMsat:%v\noutgoingAmountMsat:%v\n\n", - paymentSecret, destination, incomingAmountMsat, outgoingAmountMsat) + log.Printf("paymentHash:%x\npaymentSecret:%x\ndestination:%x\nincomingAmountMsat:%v\noutgoingAmountMsat:%v\n\n", + paymentHash, paymentSecret, destination, incomingAmountMsat, outgoingAmountMsat) if paymentSecret != nil { if fundingTxID == nil { - fundingTxID, fundingTxOutnum, err = openChannel(clientCtx, client, request.PaymentHash, destination, incomingAmountMsat) - log.Printf("openChannel(%x, %v) err: %v", destination, incomingAmountMsat, err) - if err != nil { + if bytes.Compare(paymentHash, request.PaymentHash) == 0 { + fundingTxID, fundingTxOutnum, err = openChannel(clientCtx, client, request.PaymentHash, destination, incomingAmountMsat) + log.Printf("openChannel(%x, %v) err: %v", destination, incomingAmountMsat, err) + if err != nil { + interceptorClient.Send(&routerrpc.ForwardHtlcInterceptResponse{ + IncomingCircuitKey: request.IncomingCircuitKey, + Action: routerrpc.ResolveHoldForwardAction_FAIL, + }) + continue + } + } else { //probing + failureCode := routerrpc.ForwardHtlcInterceptResponse_TEMPORARY_CHANNEL_FAILURE + if err := isConnected(clientCtx, client, destination); err == nil { + failureCode = routerrpc.ForwardHtlcInterceptResponse_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS + } interceptorClient.Send(&routerrpc.ForwardHtlcInterceptResponse{ IncomingCircuitKey: request.IncomingCircuitKey, Action: routerrpc.ResolveHoldForwardAction_FAIL, + FailureCode: failureCode, }) continue } diff --git a/postgresql/migrations/000004_create_probe_payments_hash_index.down.sql b/postgresql/migrations/000004_create_probe_payments_hash_index.down.sql new file mode 100644 index 0000000..394ca43 --- /dev/null +++ b/postgresql/migrations/000004_create_probe_payments_hash_index.down.sql @@ -0,0 +1 @@ +DROP INDEX probe_payment_hash; \ No newline at end of file diff --git a/postgresql/migrations/000004_create_probe_payments_hash_index.up.sql b/postgresql/migrations/000004_create_probe_payments_hash_index.up.sql new file mode 100644 index 0000000..cef78e3 --- /dev/null +++ b/postgresql/migrations/000004_create_probe_payments_hash_index.up.sql @@ -0,0 +1 @@ +CREATE INDEX probe_payment_hash ON public.payments (sha256('probing-01:' || payment_hash)); \ No newline at end of file