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

feat(rgbpp-sdk/btc): btc rgbpp transactions #26

Merged
merged 15 commits into from
Mar 21, 2024
Merged

Conversation

ShookLyngs
Copy link
Collaborator

@ShookLyngs ShookLyngs commented Mar 17, 2024

Main changes

  1. Add sendUtxos() API for building BTC transactions with predefined inputs/outputs
  2. Add sendRgbppUtxos() API for building RGBPP sync transactions on BTC
  3. Rewrite the satoshi/fee collection process and improve flexibility
  4. Rename types/constants/functions
    • constant: MIN_COLLECTABLE_SATOSHI -> BTC_UTXO_DUST_LIMIT
    • type: UnspentOutput -> Utxo
  5. Remove networkType prop from BTC APIs

Next

Details

The sendUtxos() API

const psbt = await sendUtxos({
  inputs: [
    {
      txid: 'txid',
      vout: 1,
      value: 546,
      address: 'btc_address',
      addressType: AddressType.P2WPKH,
      scriptPk: 'script_publickey_hex',
    },
  ],
  outputs: [
    {
      data: 'commentment_hex', // RGBPP commitment
      value: 0,
      fixed: true, // the output will not be changed or deducted
    },
    {
      address: 'to_address',
      value: RGBPP_UTXO_DUST_LIMIT, // the default RGBPP UTXO dust_limit is 546
      minUtxoSatoshi: RGBPP_UTXO_DUST_LIMIT, // customize the dust_limit of the output
      protected: true, // free satoshi can be deducted, but the output cannot be removed (freeSatoshi = value - minUtxoSatoshi)
    },
  ],
  from: account.address,
  source,
})

The sendRgbppUtxos() API

const ckbVirtualTx: RawTransaction = {} as any;
const ckbCollector = new Collector({
  ckbNodeUrl: 'ckb_node_url', 
  ckbIndexerUrl: 'ckb_indexer_url'
});

const psbt = await sendRgbppUtxos({
  ckbVirtualTx, // a CKB virtual tx containing L1 -> L1 or L1 -> L2 action
  paymaster: { // if paymaster cell was included in the ckbVirtualTx, pay to paymaster
    address: 'paymaster_btc_address',
    value: 10000,
  },
  commitment: 'rgbpp_tx_commitment',
  tos: [ // the address of the generating outputs, optional, default is "from"
    'transfer_rgbpp_to_btc_address',
  ],

  ckbCollector,
  rgbppMinUtxoSatoshi: RGBPP_UTXO_DUST_LIMIT, // optional, default to 546

  from: accounts.address,
  fromPubkey: account.publicKey, // if "from" is a P2TR address, "fromPubkey" is required 
  changeAddress: 'address_to_return_change', // optional, where should the change satoshi be returned to
  minUtxoSatoshi: BTC_UTXO_DUST_LIMIT, // optional, default to 1000, officially should be 1,0000
  source,
});

Here's a L1 -> L1 example transaction, showing how A transfers 400 RGBPP to B:

// CKB
inputs:
- RGBPP_XUDT_1, lock=A, amount=1000
- CELL, lock=A
outputs:
- RGBPP_XUDT_2, lock=B, amount=400
- RGBPP_XUDT_3, lock=A, amount=600
- CELL, lock=A

// BTC
ins:
- RGBPP_UTXO_1, address=A
- UTXO, address=A
outs:
- OP_RETURN_UTXO, data=commitment
- RGBPP_UTXO_2, address=B
- RGBPP_UTXO_3, address=A
- UTXO, address=A

Since A is transferring some RGBPP assets to B, when building the BtcVirtualTx, you should specify the address for RGBPP_UTXO_2, otherwise by default the address of the RGBPP_UTXO_2 will be set to A (as the from prop specified):

tos: {
  'RGBPP_UTXO_2_address', // The address of the outs[1], optional, default is "from"
  'RGBPP_UTXO_3_address', // The address of the outs[2], optional, default is "from"
}

Output markers

This output with the fixed mark will NOT be deducted for satoshi/fee collection:

{
  address: 'to_address',
  value: 10000,
  fixed: true,
}

This output is marked as protected, so the free satoshi in this output can be deducted (but this output cannot be removed):

{
  address: 'to_address',
  value: 10000,
  protected: true,
}

This output without any marker can be deducted during the satoshi/fee collection process, and this output can be removed from the transaction if necessary:

{
  address: 'to_address',
  value: 10000,
}

Satoshi/fee collection

The satoshi/fee collection process has been rewritten for comlex situations like in a RGBPP transaction:

  1. If there are outputs matching the (output.protected == true && output.fixed == false) condition, the collection process will try to collect free satoshi from those outputs. An output's free satoshi is output.value - output.minUtxoSatoshi.
  2. If the sum of satoshi in the transaction matches (sum(inputs) > sum(outputs)), then the change satoshi can be returned in the first output that matches the (output.fixed == false && output.address == changeAddress) condition.

BTW, since the entire collection process has been rewritten, I believe we need to conduct thorough tests on the fee estimation part. Although I have added many tests to cover various scenarios, there may still be additional issues that need to be discovered. Therefore, we could greatly benefit from more tests and reviews. cc @Dawn-github.

@ShookLyngs ShookLyngs requested a review from Flouse March 17, 2024 12:32
@ShookLyngs ShookLyngs self-assigned this Mar 17, 2024
@ShookLyngs ShookLyngs changed the title [WIP] feat: btc rgbpp transactions feat(rgbpp-sdk/btc): btc rgbpp transactions Mar 19, 2024
@duanyytop
Copy link
Collaborator

I found that the constructor of DataSource needs to pass the NetworkType, so why sendUtxos and sendRgbppUtxos also need to pass the NetworkType?

@ShookLyngs
Copy link
Collaborator Author

ShookLyngs commented Mar 19, 2024

I found that the constructor of DataSource needs to pass the NetworkType, so why sendUtxos and sendRgbppUtxos also need to pass the NetworkType?

You're right, the networkType prop can be found in the DataSource instance.
It has been removed from the props of the APIs (sendBtc/sendUtxos/sendRgbppUtxos).

Copy link
Contributor

@Flouse Flouse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other codes LGTM.

@ShookLyngs ShookLyngs force-pushed the feat/btc-rgbpp-transactions branch from 3199c74 to 06c4eb1 Compare March 21, 2024 03:58
@ShookLyngs ShookLyngs force-pushed the feat/btc-rgbpp-transactions branch from 48e265b to b93177b Compare March 21, 2024 06:30
@ShookLyngs ShookLyngs requested review from Flouse and duanyytop March 21, 2024 06:34

const liveCell = await props.ckbCollector.getLiveCell(input.previousOutput);
const isRgbppLock = isRgbppLockCell(liveCell.output, isCkbMainnet);
const isRgbppTimeLock = isBtcTimeLockCell(liveCell.output, isCkbMainnet);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this line unused?

@Flouse Flouse merged commit b00596d into main Mar 21, 2024
1 check passed
@Flouse Flouse mentioned this pull request Mar 21, 2024
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants