Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add invoice spec and fix invoice implementation #77

Merged
merged 2 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading