Skip to content

Commit

Permalink
Implement change in BOLT11 r field (#277)
Browse files Browse the repository at this point in the history
* update link to bolt11 spec

* BOLT11: implement change in r field
see lightning/bolts#317
  • Loading branch information
sstone authored and pm47 committed Dec 13, 2017
1 parent c43c009 commit 6957de3
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ object PaymentHop {
* @param msat an amount to send to a payment recipient
* @return a sequence of extra hops with a pre-calculated fee for a given msat amount
*/
def buildExtra(reversePath: Seq[Hop], msat: Long): Seq[ExtraHop] = (List.empty[ExtraHop] /: reversePath) {
case (Nil, hop) => ExtraHop(hop.nodeId, hop.shortChannelId, hop.nextFee(msat), hop.cltvExpiryDelta) :: Nil
case (head :: rest, hop) => ExtraHop(hop.nodeId, hop.shortChannelId, hop.nextFee(msat + head.fee), hop.cltvExpiryDelta) :: head :: rest
def buildExtra(reversePath: Seq[Hop], msat: Long): Seq[ExtraHop] = reversePath.foldLeft(List.empty[ExtraHop]) {
case (Nil, hop) => ExtraHop(hop.nodeId, hop.shortChannelId, hop.feeBaseMsat, hop.feeProportionalMillionths, hop.cltvExpiryDelta) :: Nil
case (head :: rest, hop) => ExtraHop(hop.nodeId, hop.shortChannelId, hop.feeBaseMsat, hop.feeProportionalMillionths, hop.cltvExpiryDelta) :: head :: rest
}
}

Expand All @@ -40,6 +40,10 @@ trait PaymentHop {
case class Hop(nodeId: PublicKey, nextNodeId: PublicKey, lastUpdate: ChannelUpdate) extends PaymentHop {
def nextFee(msat: Long): Long = PaymentHop.nodeFee(lastUpdate.feeBaseMsat, lastUpdate.feeProportionalMillionths, msat)

def feeBaseMsat: Long = lastUpdate.feeBaseMsat

def feeProportionalMillionths: Long = lastUpdate.feeProportionalMillionths

def cltvExpiryDelta: Int = lastUpdate.cltvExpiryDelta

def shortChannelId: Long = lastUpdate.shortChannelId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import scala.util.Try

/**
* Lightning Payment Request
* see https://github.com/lightningnetwork/lightning-rfc/pull/183
* see https://github.com/lightningnetwork/lightning-rfc/blob/master/11-payment-encoding.md
*
* @param prefix currency prefix; lnbc for bitcoin, lntb for bitcoin testnet
* @param amount amount to pay (empty string means no amount is specified)
Expand Down Expand Up @@ -217,15 +217,16 @@ object PaymentRequest {
*
* @param nodeId node id
* @param shortChannelId channel id
* @param fee node fee
* @param feeBaseMast node fixed fee
* @param feeProportionalMillionths node proportional fee
* @param cltvExpiryDelta node cltv expiry delta
*/
case class ExtraHop(nodeId: PublicKey, shortChannelId: Long, fee: Long, cltvExpiryDelta: Int) extends PaymentHop {
case class ExtraHop(nodeId: PublicKey, shortChannelId: Long, feeBaseMast: Long, feeProportionalMillionths: Long, cltvExpiryDelta: Int) extends PaymentHop {
def pack: Seq[Byte] = nodeId.toBin ++ Protocol.writeUInt64(shortChannelId, ByteOrder.BIG_ENDIAN) ++
Protocol.writeUInt64(fee, ByteOrder.BIG_ENDIAN) ++ Protocol.writeUInt16(cltvExpiryDelta, ByteOrder.BIG_ENDIAN)
Protocol.writeUInt32(feeBaseMast, ByteOrder.BIG_ENDIAN) ++ Protocol.writeUInt32(feeProportionalMillionths, ByteOrder.BIG_ENDIAN) ++ Protocol.writeUInt16(cltvExpiryDelta, ByteOrder.BIG_ENDIAN)

// Fee is already pre-calculated for extra hops
def nextFee(msat: Long): Long = fee
def nextFee(msat: Long): Long = PaymentHop.nodeFee(feeBaseMast, feeProportionalMillionths, msat)
}

/**
Expand All @@ -244,15 +245,16 @@ object PaymentRequest {
def parse(data: Seq[Byte]) = {
val pubkey = data.slice(0, 33)
val shortChannelId = Protocol.uint64(data.slice(33, 33 + 8), ByteOrder.BIG_ENDIAN)
val fee = Protocol.uint64(data.slice(33 + 8, 33 + 8 + 8), ByteOrder.BIG_ENDIAN)
val fee_base_msat = Protocol.uint32(data.slice(33 + 8, 33 + 8 + 4), ByteOrder.BIG_ENDIAN)
val fee_proportional_millionths = Protocol.uint32(data.slice(33 + 8 + 4, 33 + 8 + 8), ByteOrder.BIG_ENDIAN)
val cltv = Protocol.uint16(data.slice(33 + 8 + 8, chunkLength), ByteOrder.BIG_ENDIAN)
ExtraHop(PublicKey(pubkey), shortChannelId, fee, cltv)
ExtraHop(PublicKey(pubkey), shortChannelId, fee_base_msat, fee_proportional_millionths, cltv)
}

def parseAll(data: Seq[Byte]): Seq[ExtraHop] =
data.grouped(chunkLength).map(parse).toList

val chunkLength: Int = 33 + 8 + 8 + 2
val chunkLength: Int = 33 + 8 + 4 + 4 + 2
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class PaymentRequestSpec extends FunSuite {
}

test("On mainnet, with fallback address 1RustyRX2oai4EYYDpQGWvEL62BBGqN9T with extra routing info to go via nodes 029e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255 then 039e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255") {
val ref = "lnbc20m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqsfpp3qjmp7lwpagxun9pygexvgpjdc4jdj85fr9yq20q82gphp2nflc7jtzrcazrra7wwgzxqc8u7754cdlpfrmccae92qgzqvzq2ps8pqqqqqqqqqqqq9qqqvpeuqafqxu92d8lr6fvg0r5gv0heeeqgcrqlnm6jhphu9y00rrhy4grqszsvpcgpy9qqqqqqqqqqqq7qqzqfnlkwydm8rg30gjku7wmxmk06sevjp53fmvrcfegvwy7d5443jvyhxsel0hulkstws7vqv400q4j3wgpk4crg49682hr4scqvmad43cqd5m7tf"
val ref = "lnbc20m1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqhp58yjmdan79s6qqdhdzgynm4zwqd5d7xmw5fk98klysy043l2ahrqsfpp3qjmp7lwpagxun9pygexvgpjdc4jdj85fr9yq20q82gphp2nflc7jtzrcazrra7wwgzxqc8u7754cdlpfrmccae92qgzqvzq2ps8pqqqqqqpqqqqq9qqqvpeuqafqxu92d8lr6fvg0r5gv0heeeqgcrqlnm6jhphu9y00rrhy4grqszsvpcgpy9qqqqqqgqqqqq7qqzqj9n4evl6mr5aj9f58zp6fyjzup6ywn3x6sk8akg5v4tgn2q8g4fhx05wf6juaxu9760yp46454gpg5mtzgerlzezqcqvjnhjh8z3g2qqdhhwkj"
val pr = PaymentRequest.read(ref)
assert(pr.prefix == "lnbc")
assert(pr.amount === Some(MilliSatoshi(2000000000L)))
Expand All @@ -106,9 +106,12 @@ class PaymentRequestSpec extends FunSuite {
assert(pr.nodeId == PublicKey(BinaryData("03e7156ae33b0a208d0744199163177e909e80176e55d97a2f221ede0f934dd9ad")))
assert(pr.description == Right(Crypto.sha256("One piece of chocolate cake, one icecream cone, one pickle, one slice of swiss cheese, one slice of salami, one lollypop, one piece of cherry pie, one sausage, one cupcake, and one slice of watermelon".getBytes)))
assert(pr.fallbackAddress === Some("1RustyRX2oai4EYYDpQGWvEL62BBGqN9T"))
assert(pr.routingInfo() === List(RoutingInfoTag(List(ExtraHop(PublicKey("029e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255"), 72623859790382856L, 20, 3), ExtraHop(PublicKey("039e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255"), 217304205466536202L, 30, 4)))))
assert(BinaryData(Protocol.writeUInt64(72623859790382856L, ByteOrder.BIG_ENDIAN)) == BinaryData("0102030405060708"))
assert(BinaryData(Protocol.writeUInt64(217304205466536202L, ByteOrder.BIG_ENDIAN)) == BinaryData("030405060708090a"))
assert(pr.routingInfo() === List(RoutingInfoTag(List(
ExtraHop(PublicKey("029e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255"), 72623859790382856L, 1, 20, 3),
ExtraHop(PublicKey("039e03a901b85534ff1e92c43c74431f7ce72046060fcf7a95c37e148f78c77255"), 217304205466536202L, 2, 30, 4)
))))
assert(BinaryData(Protocol.writeUInt64(0x0102030405060708L, ByteOrder.BIG_ENDIAN)) == BinaryData("0102030405060708"))
assert(BinaryData(Protocol.writeUInt64(0x030405060708090aL, ByteOrder.BIG_ENDIAN)) == BinaryData("030405060708090a"))
assert(pr.tags.size == 4)
assert(PaymentRequest.write(pr.sign(priv)) == ref)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,10 @@ class RouteCalculationSpec extends FunSuite {
val reverseRoute = List(hopBA, hopCB)
val extraRoute = PaymentHop.buildExtra(reverseRoute, amount.amount)

assert(extraRoute === List(ExtraHop(PublicKey("02f0b230e53723ccc331db140edc518be1ee5ab29a508104a4be2f5be922c928e8"), 24412456671576064L, 547005, 144),
ExtraHop(PublicKey("032b4af42b5e8089a7a06005ead9ac4667527390ee39c998b7b0307f0d81d7f4ac"), 23366821113626624L, 547000, 144)))
assert(extraRoute === List(
ExtraHop(PublicKey("02f0b230e53723ccc331db140edc518be1ee5ab29a508104a4be2f5be922c928e8"), 24412456671576064L, 546000, 10, 144),
ExtraHop(PublicKey("032b4af42b5e8089a7a06005ead9ac4667527390ee39c998b7b0307f0d81d7f4ac"), 23366821113626624L, 546000, 10, 144))
)

// Sender side

Expand Down

0 comments on commit 6957de3

Please sign in to comment.