Skip to content

Commit

Permalink
Merge pull request #77 from chenyukang/add-specs
Browse files Browse the repository at this point in the history
Add invoice spec and fix invoice implementation
  • Loading branch information
quake authored Jun 18, 2024
2 parents b1bc474 + 17ae7f9 commit fe4f0b2
Show file tree
Hide file tree
Showing 11 changed files with 180 additions and 223 deletions.
68 changes: 68 additions & 0 deletions docs/specs/payment-invoice.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# CKB Fiber Network Invoice Protocol

## Overall Design

CKB Fiber network invoice will be generated and parsed by CKB Fiber Node, we referred to the design of [BOLT 11](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md), and made some adjustments from an implementation perspective.

- The invoice is encode/decoded base on [molecule](https://github.com/nervosnetwork/molecule), which is widely used in the CKB projects.
- Instead of using `bech32`, we switch to `bech32m`.
- The interface and usage is similar to [lightning-invoice](https://github.com/lightningdevkit/rust-lightning/tree/main/lightning-invoice/src) as possible, but not compatible with lightning invoice, any cross-chain compatibility needs will be handled through the hub in ckb-pcn.

## Human-readable part

The human-readable part contains these two most important fields:

1. `prefix`: [mandatory] Specify the currency and network of payment
- `fibb` for the CKB mainnet, `fibb` means `fiber bytes`, since in CKB ecosystem 1 CKB equals 1 Byte.
- `fibt` for the CKB testnet
- `fibd` for the CKB dev
2. `amount`: [optional] An optional number in that currency.
- A standalone number, means the amount of CKB or UDT, for CKB it will be in unit of `shannon`, 1 CKB = 10^8 shannon
- An empty value for this field means the amount of payment is not specified, which maybe used in the scenario of donation.


## Encoding and Decoding

With `molecule`, the data part can be easily converted to bytes. Considering that the bytes generated by molecule are not optimized for space and may contain consecutive zeros when certain fields are empty, the result from `bechm32` encoding is relatively long. We use [arcode-rs](https://github.com/cgbur/arcode-rs) to compress the bytes losslessly before `bechm32` encoding, resulting in a length reduction of almost half:

`data = compressed(data part molecule bytes) + signature`

`encode(&hrp, data, Variant::Bech32m)`

For decoding, we simply perform the inverse decompression operation.

The `signature` field: [optional] with type of `[u8; 65]` = 520 bits

- The secp256k1 signature of the entire invoice, can be used to verify the integrity and correctness of the invoice, may also be used to imply the generator node of this invoice.
By default, this filed is none, the method to generate signature:
- `message_hash = SHA256-hash (((human-readable part) → bytes) + (data bytes))`
then sign it with `Secp256k1`
- It may use a customized sign function: `Secp256k1::new().sign_ecdsa_recoverable(hash, &private_key)`

## Data Part

The data part is designed to add non-mandatory fields easily, and it is very likely that new field will be added in the future:

1. `timestamp`: [mandatory] 128 bits
- milliseconds since 1970
- The time the invoice was generated
2. `payment_hash`: [mandatory] 256 bits
- SHA256 payment_hash, could specified when creating a invoice, but we need to make sure `payment_hash` is the unique identifier of a invoice.
- If creating a `HODL` invoice, a `preimage` parameter must be provided, and the `payment_hash` is generated using `blake2b_256(preimage)` when the invoice is created.
- For `AMP invoices` (Atomic Multi-path Payments), the `payment_hash` is randomly generated.
3. `expiry`: [optional] 32 bits
- `timestamp + expiry` is the expiration time of the invoice
- Unit: seconds
4. `description`: [optional] variable length
- A string of UTF-8 text to display payment information, such as "a cup of coffee"
5. `final htlc timeout`: [optional] 32 bits
- Specifies the final htlc timeout, which may be longer because it may take more hops to reach CKB network
- Unit: seconds
6. `fallback`: [optional] variable length
- A CKB address used for fallback in case the invoice payment fails
7. `feature`: [optional] 32 bits
- Feature flag to specify features supported by the payment
8. `payee_public_key`: [optional] 33 bytes
- The public key of the payee
9. `udt_script`: [optional] variable length
- The script specified for the UDT token
3 changes: 0 additions & 3 deletions src/ckb/schema/invoice.mol
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ option SignatureOpt (Signature);

option AmountOpt (Uint128);

// SI prefix comes from: https://en.wikipedia.org/wiki/International_System_of_Units
option SiPrefixOpt (byte);
option FeatureOpt (Uint32);

table Duration {
Expand Down Expand Up @@ -85,7 +83,6 @@ table RawInvoiceData {
table RawCkbInvoice {
currency: byte,
amount: AmountOpt,
prefix: SiPrefixOpt,
signature: SignatureOpt,
data: RawInvoiceData,
}
Loading

0 comments on commit fe4f0b2

Please sign in to comment.