Skip to content

Run Bark captaind: version floor, version-3 submit, TRUC, 0-value anchor #1164

Open

Description

@mvuk

What this is

Bark's Ark server, captaind, speaks only Bitcoin Core JSON-RPC. This issue is the set of changes that let a current captaind boot and broadcast on this node, without turning libre relay into Core standardness.

Measured against:

Captaind's boot gate is in server/src/bitcoind.rs: network match, getnetworkinfo.version >= 310000, and getindexinfo reporting txindex. The 310000 floor exists because Core 31 added getmempoolentry's chunkweight and fees.chunk. This node already returns those fields. The round-funding transaction is version 2 (server/src/wallet/mod.rs). The vtxo tree, forfeits, connectors, and the exit CPFP are version 3, and the exit is submitpackage of [progress_tx, cpfp_tx] where the parent is 0-fee and carries fee_anchor() (Amount::ZERO).

Already in place

These are not open work. A regtest probe of fb991651 against captaind's client (bitcoincore-rpc 0.19, the same crate bark pins) got through every boot and round call except the two gates in the first two drafts below:

  • cookie auth on 127.0.0.1
  • getblockcount, getblockhash, getblockheader, getrawtransaction (verbose and hex), gettxout (null result included), gettxspendingprevout
  • getindexinfo → { "txindex": { "synced": true, "best_block_height": N } }
  • getmempoolentry including chunkweight and fees.chunk (vsize is chunkweight)
  • submitpackage in the Core shape (package_msg, tx-results keyed by wtxid, replaced-transactions)
  • estimatesmartfee with conf_target and estimate_mode. An empty mempool omits feerate and returns errors: ["Insufficient data or no feerate found"], which is Core's current shape. Captaind logs that and uses its fallback rates.
  • sendrawtransaction of an already-confirmed spend returns -25 RPC_VERIFY_ALREADY_IN_UTXO_SET, which captaind swallows on rebroadcast
  • duplicate sendrawtransaction returns the txid. Captaind treats Ok as success
  • getmempoolentry of a missing tx is -5, so captaind's chunk-fee lookup becomes Ok(None)
  • the round's BDK Emitter synced a fresh rounds wallet across getblock verbosity 0 and 2

The four changes

Each one is a draft. Libre relay stays: 0.1 sat/vB, no numeric dust floor, full RBF, P2P still admits any nVersion.

  1. Reported version. Default getnetworkinfo.version stays 190000 so existing clients keep the Core 0.19 getblockchaininfo shape. --rpc-client-version=310000 (conf rpc_client_version=) raises only that integer. Captaind will not boot below 310000. rpc: let operators raise getnetworkinfo.version #1159
  2. Version 3 on RPC submit. sendrawtransaction, testmempoolaccept, and submitpackage reject every nVersion other than 1 or 2 before accept. Captaind's tree, forfeit, connector, and CPFP transactions are version 3. P2P already allows them. Other versions stay rejected. rpc: admit nVersion 3 on submit #1160
  3. BIP 431 TRUC. A version-3 transaction may have one unconfirmed ancestor and one unconfirmed descendant, at most 10,000 vB, and at most 1,000 vB when that ancestor is unconfirmed. Parent and child must both be version 3. Replacing the existing child is allowed because that child conflicts. A second child that spends a different output is truc-descendant-count (no sibling eviction). Full RBF and the package feerate waiver already cover the other two BIP 431 rules. mempool: enforce BIP 431 TRUC topology #1161
  4. The 0-value anchor. One 0-value spendable output may enter when the fee is 0 and a later package member spends it. A child that spends the parent and leaves that output is missing-ephemeral-spends. A fee-paying transaction, a second 0-value output, and a lone sendrawtransaction stay dust. This is not a pay-to-anchor special case. mempool: admit one 0-value output inside a package #1163

#1159 and #1160 are independent. #1161 and #1163 both edit crates/rbitcoin-mempool/src/accept.rs in different places (the fee-floor tail, and the shape check plus accept_package). Whichever lands second needs a rebase.

Not captaind, and not in these drafts

  • ZMQ. Captaind polls. The bark client and the test harness use ZMQ; the server does not require it to run.
  • Esplora scripthash byte order and POST /txs/package. That is the bark wallet, not captaind.
  • --sh-index. Captaind does not read scripthashes.
  • RPC user/password. Cookie auth is what captaind is pointed at here.
  • Raising the default getnetworkinfo.version. A higher default would make old bitcoincore-rpc clients look for wallet RPC this node does not have.

Operator shape, once the drafts are in

rbitcoin-node --network signet --milestone 0 \
  --rpc-listen 127.0.0.1:38332 \
  --rpc-cookie-file <cookie> \
  --rpc-client-version=310000

Captaind's bitcoind_url is that RPC port and the cookie's user:password. No second wallet.

Activity

  1. mvuk commented on Oct 23, 2026

    @mvuk
    Author

    The broader goal, full captaind and bark suite coverage with no Esplora or electrs, is #1165. This issue stays the four protocol slices.

  2. mvuk commented on Oct 24, 2026

    @mvuk
    Author

    Look: captaind and bark run on rbitcoin, regtest and signet

    Regtest: the full captaind + bark suite is 592/592 on this node, Lightning included (details on #1165).

    Signet: a captaind and two bark wallets run against a synced rbitcoin signet node as their only chain source (cookie JSON-RPC; no Esplora, no electrs). Every on-chain transaction below was broadcast or relayed by rbitcoin and then checked on an independent observer:

    Step Transaction
    fund captaind (paid from another wallet, learned over P2P) e186841634406cf38f0302468525ad1bc5d18a96006db51497b1f636118eaddc
    board ×2 0d896c11b5629df485e495d25e1e03ac545e40ec2f95f9b25a31b808fa8701c5, 96042d86121b8a1907611e4d70c9a9c2e82b3e14c32c822be5412ccbd00ff71a
    arkoor payment off-chain, 30,000 sat
    round (refresh) 321c4b6a3de931925c2304eb9345e53fbef6bf73dda8e37a9d4c4cac82404dc8
    offboard 1de8cfd2cc22ddf05bcd1231c65819ac714659e18dc518e4b4d8569df59091e5
    unilateral exit: 0-fee v3 parent with a P2A anchor 379ea2b2f00269182e6b946292ae6927ba3282de794165a37f3ea42cedce8568
    exit CPFP child (v3, spends the anchor) a60f35139ace450526ed4bdb835d4f711b8c73cadb9ed4dbf5eee284a4e97e2e
    exit claim 7de4168c98eb9d9f3b3c5335ec592ba57cc829f8a1ad71bea0ea92a95e0e2710 (CSV 6, 34,904 sat back on-chain)

    Here is what has to land in rbitcoin for that to be real

    1. rpc: answers Core clients rely on (captaind / bark on rbitcoin) #1191: Core-client RPC answers: --rpc-client-version (was rpc: let operators raise getnetworkinfo.version #1159), gettxout mempool spends, stale-block getblock size fields, bip125-replaceable, one regtest mining call at a time.
    2. mempool, net: v3 / TRUC and 0-value anchor packages, RPC and P2P #1192: v3 / TRUC / anchor packages end to end: version-3 submit (was rpc: admit nVersion 3 on submit #1160), TRUC (was mempool: enforce BIP 431 TRUC topology #1161), the 0-value anchor (was mempool: admit one 0-value output inside a package #1163), submitpackage anchor retry, P2P 1p1c for the anchor parent and child.

    An operator runs captaind with --rpc-client-version=310000. Wallet RPC, ZMQ and an address index stay out of the list: captaind polls, and the bark harness signs its own funding.

    The four drafts are closed as superseded and point here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions