fix: wait for on-chain broadcast results - #113

Open
ovitrif wants to merge 25 commits into
mainfrom
codex/112-onchain-broadcast-result
Open

fix: wait for on-chain broadcast results#113
ovitrif wants to merge 25 commits into
mainfrom
codex/112-onchain-broadcast-result

Conversation

@ovitrif

@ovitrifovitrif commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Closes#112

Summary

  • Wait for the configured backend result before explicit on-chain sends report acceptance.
  • Return transaction-keyed rejected, not-dispatched, acceptance-unknown failure, and acceptance-unknown timeout errors through Rust, Swift, Kotlin, and Python.
  • Persist every possibly dispatched transaction and its complete RBF lineage before broadcast, reserve its inputs across restart, expose pending transaction IDs, and support exact-byte rebroadcast or explicit abandonment after external reconciliation.
  • Derive abandonment timestamps inside the aggregate wallet from wall time and tracked observation/eviction state; overflow fails before mutation.
  • Keep LDK-managed broadcasts fire-and-forget on a dedicated priority queue.
  • Require backend evidence before reconciliation, preserve only the canonical payment record, and make confirmation cleanup crash-safe across BDK, payment-store, and intent-store persistence failures.
  • Classify Bitcoin Core, Electrum, and Esplora responses conservatively, including already-known acceptance and returned-txid mismatch rejection.
  • Publish the breaking binding contract as 0.7.0-rc.67; PR fix: sigabrt runtime teardown #111 reserves rc.66.

Preview

N/A — no user-visible changes.

QA Notes

  • A deterministic backend rejection does not reach the consumer success path and does not create sent activity.
  • A timeout or operational failure after dispatch carries the original transaction ID. Consumers must reconcile or call rebroadcast_transaction for that exact ID; they must not create a second payment.
  • list_pending_broadcasts enumerates unresolved IDs. abandon_pending_broadcast is valid only after the caller proves the entire payment lineage absent from mempool and chain.
  • Swift unit NodeError cases no longer carry the legacy generated message value. The four broadcast-result cases carry txid.
  • Kotlin unit NodeException cases now have empty generated messages. The four broadcast-result cases carry txid.

Validation

  • Exact PR head: 550b99177102ba1bc5d01f9c41160765993a3520; local HEAD and upstream match; worktree clean.
  • cargo fmt --check and git diff --check: passed.
  • cargo build --all-targets --locked: passed. Existing target-name, unused-import, and unused-variable warnings remain outside this change.
  • cargo test --lib: 131 passed.
  • cargo test --features uniffi --lib: 141 passed; only the repository's existing UniFFI warnings were emitted.
  • cargo test --doc: 13 passed.
  • cargo test --features uniffi --doc: 13 passed.
  • cargo test --test multi_address_types_tests rbf::test_rbf_cross_wallet_transaction -- --exact --nocapture: passed against real bitcoind and electrs.
  • onchain_transaction_evicted_event: accepted-send indexing and pending-intent assertions passed; the final eviction injection is guarded and skipped because the bundled Bitcoin Core lacks removetx.
  • The dedicated splice integration test reaches the same pre-existing On-chain transaction signing failed path and wait on both base 03ccac798aeb907c6dda367fa4c8af6e3eaa54fa and this branch.
  • ./bindgen.sh: passed the JVM build/publish graph, Python generation, Swift XCFramework assembly, Android three-ABI build, DWARF/strip validation, 16 KiB alignment validation, native-debug-symbol packaging, and Maven Local publication.
  • Generated Swift archive SHA256: d6ccac3a6a013fbb5313d49faf4d3373b14053ede91923e9a1cd4f3230c6848c; Package.swift matches.
  • Generated Android AAR SHA256: 36ce1902372a5e6be38b93debce365445c878efa646c7ffc0697150648ad2f63; Maven Local and the bindgen output match byte-for-byte.
  • Kotlin Android/JVM common bindings match; Python generated sources compile; Swift and Android archives pass integrity checks.

Consumer validation

  • iOS branch e72a87566f672c14f4b7b5a32f72cb6615262270 compiled against the rc.67 API-equivalent XCFramework before the internal timestamp-only follow-up; final bindgen regenerated only native runtime artifacts and left generated Swift unchanged. After the expected enum-payload compatibility adaptation, Accepted, rejected, failed, timed-out, not-dispatched, maximum-send, and wrapped-error tests passed: 7 passed, 0 failed, 0 skipped.
  • Android branch e733f9c4ed4dbed701a640fe58c3799717c77b0b compiled against the rc.67 API-equivalent Maven AAR before the internal timestamp-only follow-up; final bindgen regenerated only native runtime artifacts and left generated Kotlin unchanged. Repository and UI accepted/rejected send-path tests passed: 5 passed.
  • Earlier live consumer journeys proved the product behavior end to end: accepted iOS tx 24b2dd80ebdca0610fdc2e90b589b810bd9fd2781cc33de8a55b63e6020b44f9 and Android tx bd2fb7e01eb49fefc70fc46be9466d3f209999c1668cdd9ec2aeaac1dfab703a reached mempool/activity/success; rejected iOS tx feeb000e379dc52d1c140f3fd8a01edfa7dfb29f12a8e670ab1b99a7a33f7b7a and Android tx 481280340d1e5507079c771de07ab8d0c13ace14203f6e0d508c9250ab09726b propagated RPC -26, stayed absent from mempool/chain/activity, and did not show success.
  • Both consumer worktrees were restored to their committed production rc.63 wiring and are clean. No consumer branch or artifact was published.

Release

  • No tag or release was created. rc.67 may be released from the fully pushed PR head only after a non-author approval, all required checks, and PR fix: sigabrt runtime teardown #111's rc.66 ordering are resolved. Add the release link here before merge.

@chatgpt-codex-connector

chatgpt-codex-connectorBot commented Sep 2, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

ReviewStatusCommitReview trigger
📝 Code ReviewCompleted2026-09-02T13:21:31.826968Z550b991Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit:92486e5695

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadsrc/tx_broadcaster.rs Outdated
Comment threadCHANGELOG.md Outdated
@ovitrif
ovitrif marked this pull request as draft September 2, 2026 08:47
@ovitrif
ovitrif marked this pull request as ready for review September 2, 2026 12:33

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit:431c6f9f29

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadcrates/bdk-wallet-aggregate/src/lib.rs Outdated
@ovitrif

Copy link
Copy Markdown
CollaboratorAuthor

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

Reviewed commit:550b991771

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadsrc/chain/electrum.rs Outdated
Comment threadsrc/wallet/mod.rs
Comment threadsrc/wallet/mod.rs Outdated
Comment threadsrc/payment/onchain.rs Outdated
Comment threadsrc/wallet/mod.rs Outdated
…adcast-result
# Conflicts:
#	CHANGELOG.md
#	Cargo.toml
#	Package.swift
#	bindings/kotlin/ldk-node-android/gradle.properties
#	bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/arm64-v8a/libldk_node.so
#	bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/armeabi-v7a/libldk_node.so
#	bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/x86_64/libldk_node.so
#	bindings/kotlin/ldk-node-jvm/gradle.properties
#	bindings/kotlin/ldk-node-jvm/lib/src/main/resources/darwin-aarch64/libldk_node.dylib
#	bindings/kotlin/ldk-node-jvm/lib/src/main/resources/darwin-x86-64/libldk_node.dylib
#	bindings/python/pyproject.toml
#	src/chain/electrum.rs
Comment threadbindings/ldk_node.udl
[Throws=NodeError]
Txid rebroadcast_transaction([ByRef]Txid txid);
[Throws=NodeError]
sequence<PendingBroadcastInfo> list_pending_broadcasts();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Reminder to run ./bindgen.sh before merge. The UDL now returns PendingBroadcastInfo, but the checked-in Swift, Kotlin, and Python bindings still return Txid, so they need to be regenerated together with the native artifacts and the Package.swift checksum.

Comment threadsrc/chain/mod.rs
}
}

for txid in wallet.take_locally_applied_unconfirmed_txids() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

note_locally_applied_unconfirmed runs before backend dispatch, but these markers are emitted unconditionally. In particular, reject_rbf_broadcast does not remove the rejected replacement marker, and a transaction confirmed before the first sync can emit Confirmed followed by Received. Could we clear the marker on RBF rejection and skip absent or already-confirmed transactions here?

Comment threadsrc/wallet/mod.rs
original_tx,
tx.clone(),
)?;
self.write_broadcast_intent(&replacement_intent)?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

write_broadcast_intent runs before next_broadcast_timestamp. If an existing lineage contains u64::MAX - 1, the timestamp call fails after the new active replacement has been persisted but before BDK records it. Restart then fails while reapplying the missing active transaction. Could we calculate the timestamp before persisting the replacement, or roll the intent back, and add an RBF restart test for this boundary?

Sign up for freeto 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.

On-chain send returns before backend broadcast result

2 participants

@ovitrif@ben-kaufman
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

fix: wait for on-chain broadcast results - #113

Open
ovitrif wants to merge 25 commits into
mainfrom
codex/112-onchain-broadcast-result
Open

fix: wait for on-chain broadcast results#113
ovitrif wants to merge 25 commits into
mainfrom
codex/112-onchain-broadcast-result

Conversation

@ovitrif

@ovitrifovitrif commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Closes#112

Summary

  • Wait for the configured backend result before explicit on-chain sends report acceptance.
  • Return transaction-keyed rejected, not-dispatched, acceptance-unknown failure, and acceptance-unknown timeout errors through Rust, Swift, Kotlin, and Python.
  • Persist every possibly dispatched transaction and its complete RBF lineage before broadcast, reserve its inputs across restart, expose pending transaction IDs, and support exact-byte rebroadcast or explicit abandonment after external reconciliation.
  • Derive abandonment timestamps inside the aggregate wallet from wall time and tracked observation/eviction state; overflow fails before mutation.
  • Keep LDK-managed broadcasts fire-and-forget on a dedicated priority queue.
  • Require backend evidence before reconciliation, preserve only the canonical payment record, and make confirmation cleanup crash-safe across BDK, payment-store, and intent-store persistence failures.
  • Classify Bitcoin Core, Electrum, and Esplora responses conservatively, including already-known acceptance and returned-txid mismatch rejection.
  • Publish the breaking binding contract as 0.7.0-rc.67; PR fix: sigabrt runtime teardown #111 reserves rc.66.

Preview

N/A — no user-visible changes.

QA Notes

  • A deterministic backend rejection does not reach the consumer success path and does not create sent activity.
  • A timeout or operational failure after dispatch carries the original transaction ID. Consumers must reconcile or call rebroadcast_transaction for that exact ID; they must not create a second payment.
  • list_pending_broadcasts enumerates unresolved IDs. abandon_pending_broadcast is valid only after the caller proves the entire payment lineage absent from mempool and chain.
  • Swift unit NodeError cases no longer carry the legacy generated message value. The four broadcast-result cases carry txid.
  • Kotlin unit NodeException cases now have empty generated messages. The four broadcast-result cases carry txid.

Validation

  • Exact PR head: 550b99177102ba1bc5d01f9c41160765993a3520; local HEAD and upstream match; worktree clean.
  • cargo fmt --check and git diff --check: passed.
  • cargo build --all-targets --locked: passed. Existing target-name, unused-import, and unused-variable warnings remain outside this change.
  • cargo test --lib: 131 passed.
  • cargo test --features uniffi --lib: 141 passed; only the repository's existing UniFFI warnings were emitted.
  • cargo test --doc: 13 passed.
  • cargo test --features uniffi --doc: 13 passed.
  • cargo test --test multi_address_types_tests rbf::test_rbf_cross_wallet_transaction -- --exact --nocapture: passed against real bitcoind and electrs.
  • onchain_transaction_evicted_event: accepted-send indexing and pending-intent assertions passed; the final eviction injection is guarded and skipped because the bundled Bitcoin Core lacks removetx.
  • The dedicated splice integration test reaches the same pre-existing On-chain transaction signing failed path and wait on both base 03ccac798aeb907c6dda367fa4c8af6e3eaa54fa and this branch.
  • ./bindgen.sh: passed the JVM build/publish graph, Python generation, Swift XCFramework assembly, Android three-ABI build, DWARF/strip validation, 16 KiB alignment validation, native-debug-symbol packaging, and Maven Local publication.
  • Generated Swift archive SHA256: d6ccac3a6a013fbb5313d49faf4d3373b14053ede91923e9a1cd4f3230c6848c; Package.swift matches.
  • Generated Android AAR SHA256: 36ce1902372a5e6be38b93debce365445c878efa646c7ffc0697150648ad2f63; Maven Local and the bindgen output match byte-for-byte.
  • Kotlin Android/JVM common bindings match; Python generated sources compile; Swift and Android archives pass integrity checks.

Consumer validation

  • iOS branch e72a87566f672c14f4b7b5a32f72cb6615262270 compiled against the rc.67 API-equivalent XCFramework before the internal timestamp-only follow-up; final bindgen regenerated only native runtime artifacts and left generated Swift unchanged. After the expected enum-payload compatibility adaptation, Accepted, rejected, failed, timed-out, not-dispatched, maximum-send, and wrapped-error tests passed: 7 passed, 0 failed, 0 skipped.
  • Android branch e733f9c4ed4dbed701a640fe58c3799717c77b0b compiled against the rc.67 API-equivalent Maven AAR before the internal timestamp-only follow-up; final bindgen regenerated only native runtime artifacts and left generated Kotlin unchanged. Repository and UI accepted/rejected send-path tests passed: 5 passed.
  • Earlier live consumer journeys proved the product behavior end to end: accepted iOS tx 24b2dd80ebdca0610fdc2e90b589b810bd9fd2781cc33de8a55b63e6020b44f9 and Android tx bd2fb7e01eb49fefc70fc46be9466d3f209999c1668cdd9ec2aeaac1dfab703a reached mempool/activity/success; rejected iOS tx feeb000e379dc52d1c140f3fd8a01edfa7dfb29f12a8e670ab1b99a7a33f7b7a and Android tx 481280340d1e5507079c771de07ab8d0c13ace14203f6e0d508c9250ab09726b propagated RPC -26, stayed absent from mempool/chain/activity, and did not show success.
  • Both consumer worktrees were restored to their committed production rc.63 wiring and are clean. No consumer branch or artifact was published.

Release

  • No tag or release was created. rc.67 may be released from the fully pushed PR head only after a non-author approval, all required checks, and PR fix: sigabrt runtime teardown #111's rc.66 ordering are resolved. Add the release link here before merge.

@chatgpt-codex-connector

chatgpt-codex-connectorBot commented Sep 2, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

ReviewStatusCommitReview trigger
📝 Code ReviewCompleted2026-09-02T13:21:31.826968Z550b991Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit:92486e5695

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadsrc/tx_broadcaster.rs Outdated
Comment threadCHANGELOG.md Outdated
@ovitrif
ovitrif marked this pull request as draft September 2, 2026 08:47
@ovitrif
ovitrif marked this pull request as ready for review September 2, 2026 12:33

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit:431c6f9f29

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadcrates/bdk-wallet-aggregate/src/lib.rs Outdated
@ovitrif

Copy link
Copy Markdown
CollaboratorAuthor

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

Reviewed commit:550b991771

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadsrc/chain/electrum.rs Outdated
Comment threadsrc/wallet/mod.rs
Comment threadsrc/wallet/mod.rs Outdated
Comment threadsrc/payment/onchain.rs Outdated
Comment threadsrc/wallet/mod.rs Outdated
…adcast-result
# Conflicts:
#	CHANGELOG.md
#	Cargo.toml
#	Package.swift
#	bindings/kotlin/ldk-node-android/gradle.properties
#	bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/arm64-v8a/libldk_node.so
#	bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/armeabi-v7a/libldk_node.so
#	bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/x86_64/libldk_node.so
#	bindings/kotlin/ldk-node-jvm/gradle.properties
#	bindings/kotlin/ldk-node-jvm/lib/src/main/resources/darwin-aarch64/libldk_node.dylib
#	bindings/kotlin/ldk-node-jvm/lib/src/main/resources/darwin-x86-64/libldk_node.dylib
#	bindings/python/pyproject.toml
#	src/chain/electrum.rs
Comment threadbindings/ldk_node.udl
[Throws=NodeError]
Txid rebroadcast_transaction([ByRef]Txid txid);
[Throws=NodeError]
sequence<PendingBroadcastInfo> list_pending_broadcasts();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Reminder to run ./bindgen.sh before merge. The UDL now returns PendingBroadcastInfo, but the checked-in Swift, Kotlin, and Python bindings still return Txid, so they need to be regenerated together with the native artifacts and the Package.swift checksum.

Comment threadsrc/chain/mod.rs
}
}

for txid in wallet.take_locally_applied_unconfirmed_txids() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

note_locally_applied_unconfirmed runs before backend dispatch, but these markers are emitted unconditionally. In particular, reject_rbf_broadcast does not remove the rejected replacement marker, and a transaction confirmed before the first sync can emit Confirmed followed by Received. Could we clear the marker on RBF rejection and skip absent or already-confirmed transactions here?

Comment threadsrc/wallet/mod.rs
original_tx,
tx.clone(),
)?;
self.write_broadcast_intent(&replacement_intent)?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

write_broadcast_intent runs before next_broadcast_timestamp. If an existing lineage contains u64::MAX - 1, the timestamp call fails after the new active replacement has been persisted but before BDK records it. Restart then fails while reapplying the missing active transaction. Could we calculate the timestamp before persisting the replacement, or roll the intent back, and add an RBF restart test for this boundary?

Sign up for freeto 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.

On-chain send returns before backend broadcast result

2 participants

@ovitrif@ben-kaufman
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: wait for on-chain broadcast results - #113

Open
ovitrif wants to merge 25 commits into
mainfrom
codex/112-onchain-broadcast-result
Open

fix: wait for on-chain broadcast results#113
ovitrif wants to merge 25 commits into
mainfrom
codex/112-onchain-broadcast-result

Conversation

@ovitrif

@ovitrifovitrif commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Closes#112

Summary

  • Wait for the configured backend result before explicit on-chain sends report acceptance.
  • Return transaction-keyed rejected, not-dispatched, acceptance-unknown failure, and acceptance-unknown timeout errors through Rust, Swift, Kotlin, and Python.
  • Persist every possibly dispatched transaction and its complete RBF lineage before broadcast, reserve its inputs across restart, expose pending transaction IDs, and support exact-byte rebroadcast or explicit abandonment after external reconciliation.
  • Derive abandonment timestamps inside the aggregate wallet from wall time and tracked observation/eviction state; overflow fails before mutation.
  • Keep LDK-managed broadcasts fire-and-forget on a dedicated priority queue.
  • Require backend evidence before reconciliation, preserve only the canonical payment record, and make confirmation cleanup crash-safe across BDK, payment-store, and intent-store persistence failures.
  • Classify Bitcoin Core, Electrum, and Esplora responses conservatively, including already-known acceptance and returned-txid mismatch rejection.
  • Publish the breaking binding contract as 0.7.0-rc.67; PR fix: sigabrt runtime teardown #111 reserves rc.66.

Preview

N/A — no user-visible changes.

QA Notes

  • A deterministic backend rejection does not reach the consumer success path and does not create sent activity.
  • A timeout or operational failure after dispatch carries the original transaction ID. Consumers must reconcile or call rebroadcast_transaction for that exact ID; they must not create a second payment.
  • list_pending_broadcasts enumerates unresolved IDs. abandon_pending_broadcast is valid only after the caller proves the entire payment lineage absent from mempool and chain.
  • Swift unit NodeError cases no longer carry the legacy generated message value. The four broadcast-result cases carry txid.
  • Kotlin unit NodeException cases now have empty generated messages. The four broadcast-result cases carry txid.

Validation

  • Exact PR head: 550b99177102ba1bc5d01f9c41160765993a3520; local HEAD and upstream match; worktree clean.
  • cargo fmt --check and git diff --check: passed.
  • cargo build --all-targets --locked: passed. Existing target-name, unused-import, and unused-variable warnings remain outside this change.
  • cargo test --lib: 131 passed.
  • cargo test --features uniffi --lib: 141 passed; only the repository's existing UniFFI warnings were emitted.
  • cargo test --doc: 13 passed.
  • cargo test --features uniffi --doc: 13 passed.
  • cargo test --test multi_address_types_tests rbf::test_rbf_cross_wallet_transaction -- --exact --nocapture: passed against real bitcoind and electrs.
  • onchain_transaction_evicted_event: accepted-send indexing and pending-intent assertions passed; the final eviction injection is guarded and skipped because the bundled Bitcoin Core lacks removetx.
  • The dedicated splice integration test reaches the same pre-existing On-chain transaction signing failed path and wait on both base 03ccac798aeb907c6dda367fa4c8af6e3eaa54fa and this branch.
  • ./bindgen.sh: passed the JVM build/publish graph, Python generation, Swift XCFramework assembly, Android three-ABI build, DWARF/strip validation, 16 KiB alignment validation, native-debug-symbol packaging, and Maven Local publication.
  • Generated Swift archive SHA256: d6ccac3a6a013fbb5313d49faf4d3373b14053ede91923e9a1cd4f3230c6848c; Package.swift matches.
  • Generated Android AAR SHA256: 36ce1902372a5e6be38b93debce365445c878efa646c7ffc0697150648ad2f63; Maven Local and the bindgen output match byte-for-byte.
  • Kotlin Android/JVM common bindings match; Python generated sources compile; Swift and Android archives pass integrity checks.

Consumer validation

  • iOS branch e72a87566f672c14f4b7b5a32f72cb6615262270 compiled against the rc.67 API-equivalent XCFramework before the internal timestamp-only follow-up; final bindgen regenerated only native runtime artifacts and left generated Swift unchanged. After the expected enum-payload compatibility adaptation, Accepted, rejected, failed, timed-out, not-dispatched, maximum-send, and wrapped-error tests passed: 7 passed, 0 failed, 0 skipped.
  • Android branch e733f9c4ed4dbed701a640fe58c3799717c77b0b compiled against the rc.67 API-equivalent Maven AAR before the internal timestamp-only follow-up; final bindgen regenerated only native runtime artifacts and left generated Kotlin unchanged. Repository and UI accepted/rejected send-path tests passed: 5 passed.
  • Earlier live consumer journeys proved the product behavior end to end: accepted iOS tx 24b2dd80ebdca0610fdc2e90b589b810bd9fd2781cc33de8a55b63e6020b44f9 and Android tx bd2fb7e01eb49fefc70fc46be9466d3f209999c1668cdd9ec2aeaac1dfab703a reached mempool/activity/success; rejected iOS tx feeb000e379dc52d1c140f3fd8a01edfa7dfb29f12a8e670ab1b99a7a33f7b7a and Android tx 481280340d1e5507079c771de07ab8d0c13ace14203f6e0d508c9250ab09726b propagated RPC -26, stayed absent from mempool/chain/activity, and did not show success.
  • Both consumer worktrees were restored to their committed production rc.63 wiring and are clean. No consumer branch or artifact was published.

Release

  • No tag or release was created. rc.67 may be released from the fully pushed PR head only after a non-author approval, all required checks, and PR fix: sigabrt runtime teardown #111's rc.66 ordering are resolved. Add the release link here before merge.

@chatgpt-codex-connector

chatgpt-codex-connectorBot commented Sep 2, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

ReviewStatusCommitReview trigger
📝 Code ReviewCompleted2026-09-02T13:21:31.826968Z550b991Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit:92486e5695

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadsrc/tx_broadcaster.rs Outdated
Comment threadCHANGELOG.md Outdated
@ovitrif
ovitrif marked this pull request as draft September 2, 2026 08:47
@ovitrif
ovitrif marked this pull request as ready for review September 2, 2026 12:33

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit:431c6f9f29

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadcrates/bdk-wallet-aggregate/src/lib.rs Outdated
@ovitrif

Copy link
Copy Markdown
CollaboratorAuthor

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

Reviewed commit:550b991771

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadsrc/chain/electrum.rs Outdated
Comment threadsrc/wallet/mod.rs
Comment threadsrc/wallet/mod.rs Outdated
Comment threadsrc/payment/onchain.rs Outdated
Comment threadsrc/wallet/mod.rs Outdated
…adcast-result
# Conflicts:
#	CHANGELOG.md
#	Cargo.toml
#	Package.swift
#	bindings/kotlin/ldk-node-android/gradle.properties
#	bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/arm64-v8a/libldk_node.so
#	bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/armeabi-v7a/libldk_node.so
#	bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/x86_64/libldk_node.so
#	bindings/kotlin/ldk-node-jvm/gradle.properties
#	bindings/kotlin/ldk-node-jvm/lib/src/main/resources/darwin-aarch64/libldk_node.dylib
#	bindings/kotlin/ldk-node-jvm/lib/src/main/resources/darwin-x86-64/libldk_node.dylib
#	bindings/python/pyproject.toml
#	src/chain/electrum.rs
Comment threadbindings/ldk_node.udl
[Throws=NodeError]
Txid rebroadcast_transaction([ByRef]Txid txid);
[Throws=NodeError]
sequence<PendingBroadcastInfo> list_pending_broadcasts();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Reminder to run ./bindgen.sh before merge. The UDL now returns PendingBroadcastInfo, but the checked-in Swift, Kotlin, and Python bindings still return Txid, so they need to be regenerated together with the native artifacts and the Package.swift checksum.

Comment threadsrc/chain/mod.rs
}
}

for txid in wallet.take_locally_applied_unconfirmed_txids() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

note_locally_applied_unconfirmed runs before backend dispatch, but these markers are emitted unconditionally. In particular, reject_rbf_broadcast does not remove the rejected replacement marker, and a transaction confirmed before the first sync can emit Confirmed followed by Received. Could we clear the marker on RBF rejection and skip absent or already-confirmed transactions here?

Comment threadsrc/wallet/mod.rs
original_tx,
tx.clone(),
)?;
self.write_broadcast_intent(&replacement_intent)?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

write_broadcast_intent runs before next_broadcast_timestamp. If an existing lineage contains u64::MAX - 1, the timestamp call fails after the new active replacement has been persisted but before BDK records it. Restart then fails while reapplying the missing active transaction. Could we calculate the timestamp before persisting the replacement, or roll the intent back, and add an RBF restart test for this boundary?

Sign up for freeto 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.

On-chain send returns before backend broadcast result

2 participants

@ovitrif@ben-kaufman
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: wait for on-chain broadcast results - #113

Open
ovitrif wants to merge 25 commits into
mainfrom
codex/112-onchain-broadcast-result
Open

fix: wait for on-chain broadcast results#113
ovitrif wants to merge 25 commits into
mainfrom
codex/112-onchain-broadcast-result

Conversation

@ovitrif

@ovitrifovitrif commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Closes#112

Summary

  • Wait for the configured backend result before explicit on-chain sends report acceptance.
  • Return transaction-keyed rejected, not-dispatched, acceptance-unknown failure, and acceptance-unknown timeout errors through Rust, Swift, Kotlin, and Python.
  • Persist every possibly dispatched transaction and its complete RBF lineage before broadcast, reserve its inputs across restart, expose pending transaction IDs, and support exact-byte rebroadcast or explicit abandonment after external reconciliation.
  • Derive abandonment timestamps inside the aggregate wallet from wall time and tracked observation/eviction state; overflow fails before mutation.
  • Keep LDK-managed broadcasts fire-and-forget on a dedicated priority queue.
  • Require backend evidence before reconciliation, preserve only the canonical payment record, and make confirmation cleanup crash-safe across BDK, payment-store, and intent-store persistence failures.
  • Classify Bitcoin Core, Electrum, and Esplora responses conservatively, including already-known acceptance and returned-txid mismatch rejection.
  • Publish the breaking binding contract as 0.7.0-rc.67; PR fix: sigabrt runtime teardown #111 reserves rc.66.

Preview

N/A — no user-visible changes.

QA Notes

  • A deterministic backend rejection does not reach the consumer success path and does not create sent activity.
  • A timeout or operational failure after dispatch carries the original transaction ID. Consumers must reconcile or call rebroadcast_transaction for that exact ID; they must not create a second payment.
  • list_pending_broadcasts enumerates unresolved IDs. abandon_pending_broadcast is valid only after the caller proves the entire payment lineage absent from mempool and chain.
  • Swift unit NodeError cases no longer carry the legacy generated message value. The four broadcast-result cases carry txid.
  • Kotlin unit NodeException cases now have empty generated messages. The four broadcast-result cases carry txid.

Validation

  • Exact PR head: 550b99177102ba1bc5d01f9c41160765993a3520; local HEAD and upstream match; worktree clean.
  • cargo fmt --check and git diff --check: passed.
  • cargo build --all-targets --locked: passed. Existing target-name, unused-import, and unused-variable warnings remain outside this change.
  • cargo test --lib: 131 passed.
  • cargo test --features uniffi --lib: 141 passed; only the repository's existing UniFFI warnings were emitted.
  • cargo test --doc: 13 passed.
  • cargo test --features uniffi --doc: 13 passed.
  • cargo test --test multi_address_types_tests rbf::test_rbf_cross_wallet_transaction -- --exact --nocapture: passed against real bitcoind and electrs.
  • onchain_transaction_evicted_event: accepted-send indexing and pending-intent assertions passed; the final eviction injection is guarded and skipped because the bundled Bitcoin Core lacks removetx.
  • The dedicated splice integration test reaches the same pre-existing On-chain transaction signing failed path and wait on both base 03ccac798aeb907c6dda367fa4c8af6e3eaa54fa and this branch.
  • ./bindgen.sh: passed the JVM build/publish graph, Python generation, Swift XCFramework assembly, Android three-ABI build, DWARF/strip validation, 16 KiB alignment validation, native-debug-symbol packaging, and Maven Local publication.
  • Generated Swift archive SHA256: d6ccac3a6a013fbb5313d49faf4d3373b14053ede91923e9a1cd4f3230c6848c; Package.swift matches.
  • Generated Android AAR SHA256: 36ce1902372a5e6be38b93debce365445c878efa646c7ffc0697150648ad2f63; Maven Local and the bindgen output match byte-for-byte.
  • Kotlin Android/JVM common bindings match; Python generated sources compile; Swift and Android archives pass integrity checks.

Consumer validation

  • iOS branch e72a87566f672c14f4b7b5a32f72cb6615262270 compiled against the rc.67 API-equivalent XCFramework before the internal timestamp-only follow-up; final bindgen regenerated only native runtime artifacts and left generated Swift unchanged. After the expected enum-payload compatibility adaptation, Accepted, rejected, failed, timed-out, not-dispatched, maximum-send, and wrapped-error tests passed: 7 passed, 0 failed, 0 skipped.
  • Android branch e733f9c4ed4dbed701a640fe58c3799717c77b0b compiled against the rc.67 API-equivalent Maven AAR before the internal timestamp-only follow-up; final bindgen regenerated only native runtime artifacts and left generated Kotlin unchanged. Repository and UI accepted/rejected send-path tests passed: 5 passed.
  • Earlier live consumer journeys proved the product behavior end to end: accepted iOS tx 24b2dd80ebdca0610fdc2e90b589b810bd9fd2781cc33de8a55b63e6020b44f9 and Android tx bd2fb7e01eb49fefc70fc46be9466d3f209999c1668cdd9ec2aeaac1dfab703a reached mempool/activity/success; rejected iOS tx feeb000e379dc52d1c140f3fd8a01edfa7dfb29f12a8e670ab1b99a7a33f7b7a and Android tx 481280340d1e5507079c771de07ab8d0c13ace14203f6e0d508c9250ab09726b propagated RPC -26, stayed absent from mempool/chain/activity, and did not show success.
  • Both consumer worktrees were restored to their committed production rc.63 wiring and are clean. No consumer branch or artifact was published.

Release

  • No tag or release was created. rc.67 may be released from the fully pushed PR head only after a non-author approval, all required checks, and PR fix: sigabrt runtime teardown #111's rc.66 ordering are resolved. Add the release link here before merge.

@chatgpt-codex-connector

chatgpt-codex-connectorBot commented Sep 2, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

ReviewStatusCommitReview trigger
📝 Code ReviewCompleted2026-09-02T13:21:31.826968Z550b991Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit:92486e5695

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadsrc/tx_broadcaster.rs Outdated
Comment threadCHANGELOG.md Outdated
@ovitrif
ovitrif marked this pull request as draft September 2, 2026 08:47
@ovitrif
ovitrif marked this pull request as ready for review September 2, 2026 12:33

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit:431c6f9f29

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadcrates/bdk-wallet-aggregate/src/lib.rs Outdated
@ovitrif

Copy link
Copy Markdown
CollaboratorAuthor

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

Reviewed commit:550b991771

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadsrc/chain/electrum.rs Outdated
Comment threadsrc/wallet/mod.rs
Comment threadsrc/wallet/mod.rs Outdated
Comment threadsrc/payment/onchain.rs Outdated
Comment threadsrc/wallet/mod.rs Outdated
…adcast-result
# Conflicts:
#	CHANGELOG.md
#	Cargo.toml
#	Package.swift
#	bindings/kotlin/ldk-node-android/gradle.properties
#	bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/arm64-v8a/libldk_node.so
#	bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/armeabi-v7a/libldk_node.so
#	bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/x86_64/libldk_node.so
#	bindings/kotlin/ldk-node-jvm/gradle.properties
#	bindings/kotlin/ldk-node-jvm/lib/src/main/resources/darwin-aarch64/libldk_node.dylib
#	bindings/kotlin/ldk-node-jvm/lib/src/main/resources/darwin-x86-64/libldk_node.dylib
#	bindings/python/pyproject.toml
#	src/chain/electrum.rs
Comment threadbindings/ldk_node.udl
[Throws=NodeError]
Txid rebroadcast_transaction([ByRef]Txid txid);
[Throws=NodeError]
sequence<PendingBroadcastInfo> list_pending_broadcasts();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Reminder to run ./bindgen.sh before merge. The UDL now returns PendingBroadcastInfo, but the checked-in Swift, Kotlin, and Python bindings still return Txid, so they need to be regenerated together with the native artifacts and the Package.swift checksum.

Comment threadsrc/chain/mod.rs
}
}

for txid in wallet.take_locally_applied_unconfirmed_txids() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

note_locally_applied_unconfirmed runs before backend dispatch, but these markers are emitted unconditionally. In particular, reject_rbf_broadcast does not remove the rejected replacement marker, and a transaction confirmed before the first sync can emit Confirmed followed by Received. Could we clear the marker on RBF rejection and skip absent or already-confirmed transactions here?

Comment threadsrc/wallet/mod.rs
original_tx,
tx.clone(),
)?;
self.write_broadcast_intent(&replacement_intent)?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

write_broadcast_intent runs before next_broadcast_timestamp. If an existing lineage contains u64::MAX - 1, the timestamp call fails after the new active replacement has been persisted but before BDK records it. Restart then fails while reapplying the missing active transaction. Could we calculate the timestamp before persisting the replacement, or roll the intent back, and add an RBF restart test for this boundary?

Sign up for freeto 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.

On-chain send returns before backend broadcast result

2 participants

@ovitrif@ben-kaufman
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

fix: wait for on-chain broadcast results - #113

Open
ovitrif wants to merge 25 commits into
mainfrom
codex/112-onchain-broadcast-result
Open

fix: wait for on-chain broadcast results#113
ovitrif wants to merge 25 commits into
mainfrom
codex/112-onchain-broadcast-result

Conversation

@ovitrif

@ovitrifovitrif commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Closes#112

Summary

  • Wait for the configured backend result before explicit on-chain sends report acceptance.
  • Return transaction-keyed rejected, not-dispatched, acceptance-unknown failure, and acceptance-unknown timeout errors through Rust, Swift, Kotlin, and Python.
  • Persist every possibly dispatched transaction and its complete RBF lineage before broadcast, reserve its inputs across restart, expose pending transaction IDs, and support exact-byte rebroadcast or explicit abandonment after external reconciliation.
  • Derive abandonment timestamps inside the aggregate wallet from wall time and tracked observation/eviction state; overflow fails before mutation.
  • Keep LDK-managed broadcasts fire-and-forget on a dedicated priority queue.
  • Require backend evidence before reconciliation, preserve only the canonical payment record, and make confirmation cleanup crash-safe across BDK, payment-store, and intent-store persistence failures.
  • Classify Bitcoin Core, Electrum, and Esplora responses conservatively, including already-known acceptance and returned-txid mismatch rejection.
  • Publish the breaking binding contract as 0.7.0-rc.67; PR fix: sigabrt runtime teardown #111 reserves rc.66.

Preview

N/A — no user-visible changes.

QA Notes

  • A deterministic backend rejection does not reach the consumer success path and does not create sent activity.
  • A timeout or operational failure after dispatch carries the original transaction ID. Consumers must reconcile or call rebroadcast_transaction for that exact ID; they must not create a second payment.
  • list_pending_broadcasts enumerates unresolved IDs. abandon_pending_broadcast is valid only after the caller proves the entire payment lineage absent from mempool and chain.
  • Swift unit NodeError cases no longer carry the legacy generated message value. The four broadcast-result cases carry txid.
  • Kotlin unit NodeException cases now have empty generated messages. The four broadcast-result cases carry txid.

Validation

  • Exact PR head: 550b99177102ba1bc5d01f9c41160765993a3520; local HEAD and upstream match; worktree clean.
  • cargo fmt --check and git diff --check: passed.
  • cargo build --all-targets --locked: passed. Existing target-name, unused-import, and unused-variable warnings remain outside this change.
  • cargo test --lib: 131 passed.
  • cargo test --features uniffi --lib: 141 passed; only the repository's existing UniFFI warnings were emitted.
  • cargo test --doc: 13 passed.
  • cargo test --features uniffi --doc: 13 passed.
  • cargo test --test multi_address_types_tests rbf::test_rbf_cross_wallet_transaction -- --exact --nocapture: passed against real bitcoind and electrs.
  • onchain_transaction_evicted_event: accepted-send indexing and pending-intent assertions passed; the final eviction injection is guarded and skipped because the bundled Bitcoin Core lacks removetx.
  • The dedicated splice integration test reaches the same pre-existing On-chain transaction signing failed path and wait on both base 03ccac798aeb907c6dda367fa4c8af6e3eaa54fa and this branch.
  • ./bindgen.sh: passed the JVM build/publish graph, Python generation, Swift XCFramework assembly, Android three-ABI build, DWARF/strip validation, 16 KiB alignment validation, native-debug-symbol packaging, and Maven Local publication.
  • Generated Swift archive SHA256: d6ccac3a6a013fbb5313d49faf4d3373b14053ede91923e9a1cd4f3230c6848c; Package.swift matches.
  • Generated Android AAR SHA256: 36ce1902372a5e6be38b93debce365445c878efa646c7ffc0697150648ad2f63; Maven Local and the bindgen output match byte-for-byte.
  • Kotlin Android/JVM common bindings match; Python generated sources compile; Swift and Android archives pass integrity checks.

Consumer validation

  • iOS branch e72a87566f672c14f4b7b5a32f72cb6615262270 compiled against the rc.67 API-equivalent XCFramework before the internal timestamp-only follow-up; final bindgen regenerated only native runtime artifacts and left generated Swift unchanged. After the expected enum-payload compatibility adaptation, Accepted, rejected, failed, timed-out, not-dispatched, maximum-send, and wrapped-error tests passed: 7 passed, 0 failed, 0 skipped.
  • Android branch e733f9c4ed4dbed701a640fe58c3799717c77b0b compiled against the rc.67 API-equivalent Maven AAR before the internal timestamp-only follow-up; final bindgen regenerated only native runtime artifacts and left generated Kotlin unchanged. Repository and UI accepted/rejected send-path tests passed: 5 passed.
  • Earlier live consumer journeys proved the product behavior end to end: accepted iOS tx 24b2dd80ebdca0610fdc2e90b589b810bd9fd2781cc33de8a55b63e6020b44f9 and Android tx bd2fb7e01eb49fefc70fc46be9466d3f209999c1668cdd9ec2aeaac1dfab703a reached mempool/activity/success; rejected iOS tx feeb000e379dc52d1c140f3fd8a01edfa7dfb29f12a8e670ab1b99a7a33f7b7a and Android tx 481280340d1e5507079c771de07ab8d0c13ace14203f6e0d508c9250ab09726b propagated RPC -26, stayed absent from mempool/chain/activity, and did not show success.
  • Both consumer worktrees were restored to their committed production rc.63 wiring and are clean. No consumer branch or artifact was published.

Release

  • No tag or release was created. rc.67 may be released from the fully pushed PR head only after a non-author approval, all required checks, and PR fix: sigabrt runtime teardown #111's rc.66 ordering are resolved. Add the release link here before merge.

@chatgpt-codex-connector

chatgpt-codex-connectorBot commented Sep 2, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

ReviewStatusCommitReview trigger
📝 Code ReviewCompleted2026-09-02T13:21:31.826968Z550b991Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit:92486e5695

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadsrc/tx_broadcaster.rs Outdated
Comment threadCHANGELOG.md Outdated
@ovitrif
ovitrif marked this pull request as draft September 2, 2026 08:47
@ovitrif
ovitrif marked this pull request as ready for review September 2, 2026 12:33

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit:431c6f9f29

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadcrates/bdk-wallet-aggregate/src/lib.rs Outdated
@ovitrif

Copy link
Copy Markdown
CollaboratorAuthor

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

Reviewed commit:550b991771

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadsrc/chain/electrum.rs Outdated
Comment threadsrc/wallet/mod.rs
Comment threadsrc/wallet/mod.rs Outdated
Comment threadsrc/payment/onchain.rs Outdated
Comment threadsrc/wallet/mod.rs Outdated
…adcast-result
# Conflicts:
#	CHANGELOG.md
#	Cargo.toml
#	Package.swift
#	bindings/kotlin/ldk-node-android/gradle.properties
#	bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/arm64-v8a/libldk_node.so
#	bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/armeabi-v7a/libldk_node.so
#	bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/x86_64/libldk_node.so
#	bindings/kotlin/ldk-node-jvm/gradle.properties
#	bindings/kotlin/ldk-node-jvm/lib/src/main/resources/darwin-aarch64/libldk_node.dylib
#	bindings/kotlin/ldk-node-jvm/lib/src/main/resources/darwin-x86-64/libldk_node.dylib
#	bindings/python/pyproject.toml
#	src/chain/electrum.rs
Comment threadbindings/ldk_node.udl
[Throws=NodeError]
Txid rebroadcast_transaction([ByRef]Txid txid);
[Throws=NodeError]
sequence<PendingBroadcastInfo> list_pending_broadcasts();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Reminder to run ./bindgen.sh before merge. The UDL now returns PendingBroadcastInfo, but the checked-in Swift, Kotlin, and Python bindings still return Txid, so they need to be regenerated together with the native artifacts and the Package.swift checksum.

Comment threadsrc/chain/mod.rs
}
}

for txid in wallet.take_locally_applied_unconfirmed_txids() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

note_locally_applied_unconfirmed runs before backend dispatch, but these markers are emitted unconditionally. In particular, reject_rbf_broadcast does not remove the rejected replacement marker, and a transaction confirmed before the first sync can emit Confirmed followed by Received. Could we clear the marker on RBF rejection and skip absent or already-confirmed transactions here?

Comment threadsrc/wallet/mod.rs
original_tx,
tx.clone(),
)?;
self.write_broadcast_intent(&replacement_intent)?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

write_broadcast_intent runs before next_broadcast_timestamp. If an existing lineage contains u64::MAX - 1, the timestamp call fails after the new active replacement has been persisted but before BDK records it. Restart then fails while reapplying the missing active transaction. Could we calculate the timestamp before persisting the replacement, or roll the intent back, and add an RBF restart test for this boundary?

Sign up for freeto 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.

On-chain send returns before backend broadcast result

2 participants

@ovitrif@ben-kaufman
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: wait for on-chain broadcast results - #113

Open
ovitrif wants to merge 25 commits into
mainfrom
codex/112-onchain-broadcast-result
Open

fix: wait for on-chain broadcast results#113
ovitrif wants to merge 25 commits into
mainfrom
codex/112-onchain-broadcast-result

Conversation

@ovitrif

@ovitrifovitrif commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Closes#112

Summary

  • Wait for the configured backend result before explicit on-chain sends report acceptance.
  • Return transaction-keyed rejected, not-dispatched, acceptance-unknown failure, and acceptance-unknown timeout errors through Rust, Swift, Kotlin, and Python.
  • Persist every possibly dispatched transaction and its complete RBF lineage before broadcast, reserve its inputs across restart, expose pending transaction IDs, and support exact-byte rebroadcast or explicit abandonment after external reconciliation.
  • Derive abandonment timestamps inside the aggregate wallet from wall time and tracked observation/eviction state; overflow fails before mutation.
  • Keep LDK-managed broadcasts fire-and-forget on a dedicated priority queue.
  • Require backend evidence before reconciliation, preserve only the canonical payment record, and make confirmation cleanup crash-safe across BDK, payment-store, and intent-store persistence failures.
  • Classify Bitcoin Core, Electrum, and Esplora responses conservatively, including already-known acceptance and returned-txid mismatch rejection.
  • Publish the breaking binding contract as 0.7.0-rc.67; PR fix: sigabrt runtime teardown #111 reserves rc.66.

Preview

N/A — no user-visible changes.

QA Notes

  • A deterministic backend rejection does not reach the consumer success path and does not create sent activity.
  • A timeout or operational failure after dispatch carries the original transaction ID. Consumers must reconcile or call rebroadcast_transaction for that exact ID; they must not create a second payment.
  • list_pending_broadcasts enumerates unresolved IDs. abandon_pending_broadcast is valid only after the caller proves the entire payment lineage absent from mempool and chain.
  • Swift unit NodeError cases no longer carry the legacy generated message value. The four broadcast-result cases carry txid.
  • Kotlin unit NodeException cases now have empty generated messages. The four broadcast-result cases carry txid.

Validation

  • Exact PR head: 550b99177102ba1bc5d01f9c41160765993a3520; local HEAD and upstream match; worktree clean.
  • cargo fmt --check and git diff --check: passed.
  • cargo build --all-targets --locked: passed. Existing target-name, unused-import, and unused-variable warnings remain outside this change.
  • cargo test --lib: 131 passed.
  • cargo test --features uniffi --lib: 141 passed; only the repository's existing UniFFI warnings were emitted.
  • cargo test --doc: 13 passed.
  • cargo test --features uniffi --doc: 13 passed.
  • cargo test --test multi_address_types_tests rbf::test_rbf_cross_wallet_transaction -- --exact --nocapture: passed against real bitcoind and electrs.
  • onchain_transaction_evicted_event: accepted-send indexing and pending-intent assertions passed; the final eviction injection is guarded and skipped because the bundled Bitcoin Core lacks removetx.
  • The dedicated splice integration test reaches the same pre-existing On-chain transaction signing failed path and wait on both base 03ccac798aeb907c6dda367fa4c8af6e3eaa54fa and this branch.
  • ./bindgen.sh: passed the JVM build/publish graph, Python generation, Swift XCFramework assembly, Android three-ABI build, DWARF/strip validation, 16 KiB alignment validation, native-debug-symbol packaging, and Maven Local publication.
  • Generated Swift archive SHA256: d6ccac3a6a013fbb5313d49faf4d3373b14053ede91923e9a1cd4f3230c6848c; Package.swift matches.
  • Generated Android AAR SHA256: 36ce1902372a5e6be38b93debce365445c878efa646c7ffc0697150648ad2f63; Maven Local and the bindgen output match byte-for-byte.
  • Kotlin Android/JVM common bindings match; Python generated sources compile; Swift and Android archives pass integrity checks.

Consumer validation

  • iOS branch e72a87566f672c14f4b7b5a32f72cb6615262270 compiled against the rc.67 API-equivalent XCFramework before the internal timestamp-only follow-up; final bindgen regenerated only native runtime artifacts and left generated Swift unchanged. After the expected enum-payload compatibility adaptation, Accepted, rejected, failed, timed-out, not-dispatched, maximum-send, and wrapped-error tests passed: 7 passed, 0 failed, 0 skipped.
  • Android branch e733f9c4ed4dbed701a640fe58c3799717c77b0b compiled against the rc.67 API-equivalent Maven AAR before the internal timestamp-only follow-up; final bindgen regenerated only native runtime artifacts and left generated Kotlin unchanged. Repository and UI accepted/rejected send-path tests passed: 5 passed.
  • Earlier live consumer journeys proved the product behavior end to end: accepted iOS tx 24b2dd80ebdca0610fdc2e90b589b810bd9fd2781cc33de8a55b63e6020b44f9 and Android tx bd2fb7e01eb49fefc70fc46be9466d3f209999c1668cdd9ec2aeaac1dfab703a reached mempool/activity/success; rejected iOS tx feeb000e379dc52d1c140f3fd8a01edfa7dfb29f12a8e670ab1b99a7a33f7b7a and Android tx 481280340d1e5507079c771de07ab8d0c13ace14203f6e0d508c9250ab09726b propagated RPC -26, stayed absent from mempool/chain/activity, and did not show success.
  • Both consumer worktrees were restored to their committed production rc.63 wiring and are clean. No consumer branch or artifact was published.

Release

  • No tag or release was created. rc.67 may be released from the fully pushed PR head only after a non-author approval, all required checks, and PR fix: sigabrt runtime teardown #111's rc.66 ordering are resolved. Add the release link here before merge.

@chatgpt-codex-connector

chatgpt-codex-connectorBot commented Sep 2, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

ReviewStatusCommitReview trigger
📝 Code ReviewCompleted2026-09-02T13:21:31.826968Z550b991Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit:92486e5695

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadsrc/tx_broadcaster.rs Outdated
Comment threadCHANGELOG.md Outdated
@ovitrif
ovitrif marked this pull request as draft September 2, 2026 08:47
@ovitrif
ovitrif marked this pull request as ready for review September 2, 2026 12:33

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit:431c6f9f29

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadcrates/bdk-wallet-aggregate/src/lib.rs Outdated
@ovitrif

Copy link
Copy Markdown
CollaboratorAuthor

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

Reviewed commit:550b991771

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadsrc/chain/electrum.rs Outdated
Comment threadsrc/wallet/mod.rs
Comment threadsrc/wallet/mod.rs Outdated
Comment threadsrc/payment/onchain.rs Outdated
Comment threadsrc/wallet/mod.rs Outdated
…adcast-result
# Conflicts:
#	CHANGELOG.md
#	Cargo.toml
#	Package.swift
#	bindings/kotlin/ldk-node-android/gradle.properties
#	bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/arm64-v8a/libldk_node.so
#	bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/armeabi-v7a/libldk_node.so
#	bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/x86_64/libldk_node.so
#	bindings/kotlin/ldk-node-jvm/gradle.properties
#	bindings/kotlin/ldk-node-jvm/lib/src/main/resources/darwin-aarch64/libldk_node.dylib
#	bindings/kotlin/ldk-node-jvm/lib/src/main/resources/darwin-x86-64/libldk_node.dylib
#	bindings/python/pyproject.toml
#	src/chain/electrum.rs
Comment threadbindings/ldk_node.udl
[Throws=NodeError]
Txid rebroadcast_transaction([ByRef]Txid txid);
[Throws=NodeError]
sequence<PendingBroadcastInfo> list_pending_broadcasts();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Reminder to run ./bindgen.sh before merge. The UDL now returns PendingBroadcastInfo, but the checked-in Swift, Kotlin, and Python bindings still return Txid, so they need to be regenerated together with the native artifacts and the Package.swift checksum.

Comment threadsrc/chain/mod.rs
}
}

for txid in wallet.take_locally_applied_unconfirmed_txids() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

note_locally_applied_unconfirmed runs before backend dispatch, but these markers are emitted unconditionally. In particular, reject_rbf_broadcast does not remove the rejected replacement marker, and a transaction confirmed before the first sync can emit Confirmed followed by Received. Could we clear the marker on RBF rejection and skip absent or already-confirmed transactions here?

Comment threadsrc/wallet/mod.rs
original_tx,
tx.clone(),
)?;
self.write_broadcast_intent(&replacement_intent)?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

write_broadcast_intent runs before next_broadcast_timestamp. If an existing lineage contains u64::MAX - 1, the timestamp call fails after the new active replacement has been persisted but before BDK records it. Restart then fails while reapplying the missing active transaction. Could we calculate the timestamp before persisting the replacement, or roll the intent back, and add an RBF restart test for this boundary?

Sign up for freeto 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.

On-chain send returns before backend broadcast result

2 participants

@ovitrif@ben-kaufman
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: wait for on-chain broadcast results - #113

Open
ovitrif wants to merge 25 commits into
mainfrom
codex/112-onchain-broadcast-result
Open

fix: wait for on-chain broadcast results#113
ovitrif wants to merge 25 commits into
mainfrom
codex/112-onchain-broadcast-result

Conversation

@ovitrif

@ovitrifovitrif commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Closes#112

Summary

  • Wait for the configured backend result before explicit on-chain sends report acceptance.
  • Return transaction-keyed rejected, not-dispatched, acceptance-unknown failure, and acceptance-unknown timeout errors through Rust, Swift, Kotlin, and Python.
  • Persist every possibly dispatched transaction and its complete RBF lineage before broadcast, reserve its inputs across restart, expose pending transaction IDs, and support exact-byte rebroadcast or explicit abandonment after external reconciliation.
  • Derive abandonment timestamps inside the aggregate wallet from wall time and tracked observation/eviction state; overflow fails before mutation.
  • Keep LDK-managed broadcasts fire-and-forget on a dedicated priority queue.
  • Require backend evidence before reconciliation, preserve only the canonical payment record, and make confirmation cleanup crash-safe across BDK, payment-store, and intent-store persistence failures.
  • Classify Bitcoin Core, Electrum, and Esplora responses conservatively, including already-known acceptance and returned-txid mismatch rejection.
  • Publish the breaking binding contract as 0.7.0-rc.67; PR fix: sigabrt runtime teardown #111 reserves rc.66.

Preview

N/A — no user-visible changes.

QA Notes

  • A deterministic backend rejection does not reach the consumer success path and does not create sent activity.
  • A timeout or operational failure after dispatch carries the original transaction ID. Consumers must reconcile or call rebroadcast_transaction for that exact ID; they must not create a second payment.
  • list_pending_broadcasts enumerates unresolved IDs. abandon_pending_broadcast is valid only after the caller proves the entire payment lineage absent from mempool and chain.
  • Swift unit NodeError cases no longer carry the legacy generated message value. The four broadcast-result cases carry txid.
  • Kotlin unit NodeException cases now have empty generated messages. The four broadcast-result cases carry txid.

Validation

  • Exact PR head: 550b99177102ba1bc5d01f9c41160765993a3520; local HEAD and upstream match; worktree clean.
  • cargo fmt --check and git diff --check: passed.
  • cargo build --all-targets --locked: passed. Existing target-name, unused-import, and unused-variable warnings remain outside this change.
  • cargo test --lib: 131 passed.
  • cargo test --features uniffi --lib: 141 passed; only the repository's existing UniFFI warnings were emitted.
  • cargo test --doc: 13 passed.
  • cargo test --features uniffi --doc: 13 passed.
  • cargo test --test multi_address_types_tests rbf::test_rbf_cross_wallet_transaction -- --exact --nocapture: passed against real bitcoind and electrs.
  • onchain_transaction_evicted_event: accepted-send indexing and pending-intent assertions passed; the final eviction injection is guarded and skipped because the bundled Bitcoin Core lacks removetx.
  • The dedicated splice integration test reaches the same pre-existing On-chain transaction signing failed path and wait on both base 03ccac798aeb907c6dda367fa4c8af6e3eaa54fa and this branch.
  • ./bindgen.sh: passed the JVM build/publish graph, Python generation, Swift XCFramework assembly, Android three-ABI build, DWARF/strip validation, 16 KiB alignment validation, native-debug-symbol packaging, and Maven Local publication.
  • Generated Swift archive SHA256: d6ccac3a6a013fbb5313d49faf4d3373b14053ede91923e9a1cd4f3230c6848c; Package.swift matches.
  • Generated Android AAR SHA256: 36ce1902372a5e6be38b93debce365445c878efa646c7ffc0697150648ad2f63; Maven Local and the bindgen output match byte-for-byte.
  • Kotlin Android/JVM common bindings match; Python generated sources compile; Swift and Android archives pass integrity checks.

Consumer validation

  • iOS branch e72a87566f672c14f4b7b5a32f72cb6615262270 compiled against the rc.67 API-equivalent XCFramework before the internal timestamp-only follow-up; final bindgen regenerated only native runtime artifacts and left generated Swift unchanged. After the expected enum-payload compatibility adaptation, Accepted, rejected, failed, timed-out, not-dispatched, maximum-send, and wrapped-error tests passed: 7 passed, 0 failed, 0 skipped.
  • Android branch e733f9c4ed4dbed701a640fe58c3799717c77b0b compiled against the rc.67 API-equivalent Maven AAR before the internal timestamp-only follow-up; final bindgen regenerated only native runtime artifacts and left generated Kotlin unchanged. Repository and UI accepted/rejected send-path tests passed: 5 passed.
  • Earlier live consumer journeys proved the product behavior end to end: accepted iOS tx 24b2dd80ebdca0610fdc2e90b589b810bd9fd2781cc33de8a55b63e6020b44f9 and Android tx bd2fb7e01eb49fefc70fc46be9466d3f209999c1668cdd9ec2aeaac1dfab703a reached mempool/activity/success; rejected iOS tx feeb000e379dc52d1c140f3fd8a01edfa7dfb29f12a8e670ab1b99a7a33f7b7a and Android tx 481280340d1e5507079c771de07ab8d0c13ace14203f6e0d508c9250ab09726b propagated RPC -26, stayed absent from mempool/chain/activity, and did not show success.
  • Both consumer worktrees were restored to their committed production rc.63 wiring and are clean. No consumer branch or artifact was published.

Release

  • No tag or release was created. rc.67 may be released from the fully pushed PR head only after a non-author approval, all required checks, and PR fix: sigabrt runtime teardown #111's rc.66 ordering are resolved. Add the release link here before merge.

@chatgpt-codex-connector

chatgpt-codex-connectorBot commented Sep 2, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

ReviewStatusCommitReview trigger
📝 Code ReviewCompleted2026-09-02T13:21:31.826968Z550b991Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit:92486e5695

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadsrc/tx_broadcaster.rs Outdated
Comment threadCHANGELOG.md Outdated
@ovitrif
ovitrif marked this pull request as draft September 2, 2026 08:47
@ovitrif
ovitrif marked this pull request as ready for review September 2, 2026 12:33

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit:431c6f9f29

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadcrates/bdk-wallet-aggregate/src/lib.rs Outdated
@ovitrif

Copy link
Copy Markdown
CollaboratorAuthor

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

Reviewed commit:550b991771

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadsrc/chain/electrum.rs Outdated
Comment threadsrc/wallet/mod.rs
Comment threadsrc/wallet/mod.rs Outdated
Comment threadsrc/payment/onchain.rs Outdated
Comment threadsrc/wallet/mod.rs Outdated
…adcast-result
# Conflicts:
#	CHANGELOG.md
#	Cargo.toml
#	Package.swift
#	bindings/kotlin/ldk-node-android/gradle.properties
#	bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/arm64-v8a/libldk_node.so
#	bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/armeabi-v7a/libldk_node.so
#	bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/x86_64/libldk_node.so
#	bindings/kotlin/ldk-node-jvm/gradle.properties
#	bindings/kotlin/ldk-node-jvm/lib/src/main/resources/darwin-aarch64/libldk_node.dylib
#	bindings/kotlin/ldk-node-jvm/lib/src/main/resources/darwin-x86-64/libldk_node.dylib
#	bindings/python/pyproject.toml
#	src/chain/electrum.rs
Comment threadbindings/ldk_node.udl
[Throws=NodeError]
Txid rebroadcast_transaction([ByRef]Txid txid);
[Throws=NodeError]
sequence<PendingBroadcastInfo> list_pending_broadcasts();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Reminder to run ./bindgen.sh before merge. The UDL now returns PendingBroadcastInfo, but the checked-in Swift, Kotlin, and Python bindings still return Txid, so they need to be regenerated together with the native artifacts and the Package.swift checksum.

Comment threadsrc/chain/mod.rs
}
}

for txid in wallet.take_locally_applied_unconfirmed_txids() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

note_locally_applied_unconfirmed runs before backend dispatch, but these markers are emitted unconditionally. In particular, reject_rbf_broadcast does not remove the rejected replacement marker, and a transaction confirmed before the first sync can emit Confirmed followed by Received. Could we clear the marker on RBF rejection and skip absent or already-confirmed transactions here?

Comment threadsrc/wallet/mod.rs
original_tx,
tx.clone(),
)?;
self.write_broadcast_intent(&replacement_intent)?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

write_broadcast_intent runs before next_broadcast_timestamp. If an existing lineage contains u64::MAX - 1, the timestamp call fails after the new active replacement has been persisted but before BDK records it. Restart then fails while reapplying the missing active transaction. Could we calculate the timestamp before persisting the replacement, or roll the intent back, and add an RBF restart test for this boundary?

Sign up for freeto 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.

On-chain send returns before backend broadcast result

2 participants

@ovitrif@ben-kaufman
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

fix: wait for on-chain broadcast results - #113

Open
ovitrif wants to merge 25 commits into
mainfrom
codex/112-onchain-broadcast-result
Open

fix: wait for on-chain broadcast results#113
ovitrif wants to merge 25 commits into
mainfrom
codex/112-onchain-broadcast-result

Conversation

@ovitrif

@ovitrifovitrif commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Closes#112

Summary

  • Wait for the configured backend result before explicit on-chain sends report acceptance.
  • Return transaction-keyed rejected, not-dispatched, acceptance-unknown failure, and acceptance-unknown timeout errors through Rust, Swift, Kotlin, and Python.
  • Persist every possibly dispatched transaction and its complete RBF lineage before broadcast, reserve its inputs across restart, expose pending transaction IDs, and support exact-byte rebroadcast or explicit abandonment after external reconciliation.
  • Derive abandonment timestamps inside the aggregate wallet from wall time and tracked observation/eviction state; overflow fails before mutation.
  • Keep LDK-managed broadcasts fire-and-forget on a dedicated priority queue.
  • Require backend evidence before reconciliation, preserve only the canonical payment record, and make confirmation cleanup crash-safe across BDK, payment-store, and intent-store persistence failures.
  • Classify Bitcoin Core, Electrum, and Esplora responses conservatively, including already-known acceptance and returned-txid mismatch rejection.
  • Publish the breaking binding contract as 0.7.0-rc.67; PR fix: sigabrt runtime teardown #111 reserves rc.66.

Preview

N/A — no user-visible changes.

QA Notes

  • A deterministic backend rejection does not reach the consumer success path and does not create sent activity.
  • A timeout or operational failure after dispatch carries the original transaction ID. Consumers must reconcile or call rebroadcast_transaction for that exact ID; they must not create a second payment.
  • list_pending_broadcasts enumerates unresolved IDs. abandon_pending_broadcast is valid only after the caller proves the entire payment lineage absent from mempool and chain.
  • Swift unit NodeError cases no longer carry the legacy generated message value. The four broadcast-result cases carry txid.
  • Kotlin unit NodeException cases now have empty generated messages. The four broadcast-result cases carry txid.

Validation

  • Exact PR head: 550b99177102ba1bc5d01f9c41160765993a3520; local HEAD and upstream match; worktree clean.
  • cargo fmt --check and git diff --check: passed.
  • cargo build --all-targets --locked: passed. Existing target-name, unused-import, and unused-variable warnings remain outside this change.
  • cargo test --lib: 131 passed.
  • cargo test --features uniffi --lib: 141 passed; only the repository's existing UniFFI warnings were emitted.
  • cargo test --doc: 13 passed.
  • cargo test --features uniffi --doc: 13 passed.
  • cargo test --test multi_address_types_tests rbf::test_rbf_cross_wallet_transaction -- --exact --nocapture: passed against real bitcoind and electrs.
  • onchain_transaction_evicted_event: accepted-send indexing and pending-intent assertions passed; the final eviction injection is guarded and skipped because the bundled Bitcoin Core lacks removetx.
  • The dedicated splice integration test reaches the same pre-existing On-chain transaction signing failed path and wait on both base 03ccac798aeb907c6dda367fa4c8af6e3eaa54fa and this branch.
  • ./bindgen.sh: passed the JVM build/publish graph, Python generation, Swift XCFramework assembly, Android three-ABI build, DWARF/strip validation, 16 KiB alignment validation, native-debug-symbol packaging, and Maven Local publication.
  • Generated Swift archive SHA256: d6ccac3a6a013fbb5313d49faf4d3373b14053ede91923e9a1cd4f3230c6848c; Package.swift matches.
  • Generated Android AAR SHA256: 36ce1902372a5e6be38b93debce365445c878efa646c7ffc0697150648ad2f63; Maven Local and the bindgen output match byte-for-byte.
  • Kotlin Android/JVM common bindings match; Python generated sources compile; Swift and Android archives pass integrity checks.

Consumer validation

  • iOS branch e72a87566f672c14f4b7b5a32f72cb6615262270 compiled against the rc.67 API-equivalent XCFramework before the internal timestamp-only follow-up; final bindgen regenerated only native runtime artifacts and left generated Swift unchanged. After the expected enum-payload compatibility adaptation, Accepted, rejected, failed, timed-out, not-dispatched, maximum-send, and wrapped-error tests passed: 7 passed, 0 failed, 0 skipped.
  • Android branch e733f9c4ed4dbed701a640fe58c3799717c77b0b compiled against the rc.67 API-equivalent Maven AAR before the internal timestamp-only follow-up; final bindgen regenerated only native runtime artifacts and left generated Kotlin unchanged. Repository and UI accepted/rejected send-path tests passed: 5 passed.
  • Earlier live consumer journeys proved the product behavior end to end: accepted iOS tx 24b2dd80ebdca0610fdc2e90b589b810bd9fd2781cc33de8a55b63e6020b44f9 and Android tx bd2fb7e01eb49fefc70fc46be9466d3f209999c1668cdd9ec2aeaac1dfab703a reached mempool/activity/success; rejected iOS tx feeb000e379dc52d1c140f3fd8a01edfa7dfb29f12a8e670ab1b99a7a33f7b7a and Android tx 481280340d1e5507079c771de07ab8d0c13ace14203f6e0d508c9250ab09726b propagated RPC -26, stayed absent from mempool/chain/activity, and did not show success.
  • Both consumer worktrees were restored to their committed production rc.63 wiring and are clean. No consumer branch or artifact was published.

Release

  • No tag or release was created. rc.67 may be released from the fully pushed PR head only after a non-author approval, all required checks, and PR fix: sigabrt runtime teardown #111's rc.66 ordering are resolved. Add the release link here before merge.

@chatgpt-codex-connector

chatgpt-codex-connectorBot commented Sep 2, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

ReviewStatusCommitReview trigger
📝 Code ReviewCompleted2026-09-02T13:21:31.826968Z550b991Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit:92486e5695

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadsrc/tx_broadcaster.rs Outdated
Comment threadCHANGELOG.md Outdated
@ovitrif
ovitrif marked this pull request as draft September 2, 2026 08:47
@ovitrif
ovitrif marked this pull request as ready for review September 2, 2026 12:33

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit:431c6f9f29

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadcrates/bdk-wallet-aggregate/src/lib.rs Outdated
@ovitrif

Copy link
Copy Markdown
CollaboratorAuthor

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

Reviewed commit:550b991771

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment threadsrc/chain/electrum.rs Outdated
Comment threadsrc/wallet/mod.rs
Comment threadsrc/wallet/mod.rs Outdated
Comment threadsrc/payment/onchain.rs Outdated
Comment threadsrc/wallet/mod.rs Outdated
…adcast-result
# Conflicts:
#	CHANGELOG.md
#	Cargo.toml
#	Package.swift
#	bindings/kotlin/ldk-node-android/gradle.properties
#	bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/arm64-v8a/libldk_node.so
#	bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/armeabi-v7a/libldk_node.so
#	bindings/kotlin/ldk-node-android/lib/src/main/jniLibs/x86_64/libldk_node.so
#	bindings/kotlin/ldk-node-jvm/gradle.properties
#	bindings/kotlin/ldk-node-jvm/lib/src/main/resources/darwin-aarch64/libldk_node.dylib
#	bindings/kotlin/ldk-node-jvm/lib/src/main/resources/darwin-x86-64/libldk_node.dylib
#	bindings/python/pyproject.toml
#	src/chain/electrum.rs
Comment threadbindings/ldk_node.udl
[Throws=NodeError]
Txid rebroadcast_transaction([ByRef]Txid txid);
[Throws=NodeError]
sequence<PendingBroadcastInfo> list_pending_broadcasts();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Reminder to run ./bindgen.sh before merge. The UDL now returns PendingBroadcastInfo, but the checked-in Swift, Kotlin, and Python bindings still return Txid, so they need to be regenerated together with the native artifacts and the Package.swift checksum.

Comment threadsrc/chain/mod.rs
}
}

for txid in wallet.take_locally_applied_unconfirmed_txids() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

note_locally_applied_unconfirmed runs before backend dispatch, but these markers are emitted unconditionally. In particular, reject_rbf_broadcast does not remove the rejected replacement marker, and a transaction confirmed before the first sync can emit Confirmed followed by Received. Could we clear the marker on RBF rejection and skip absent or already-confirmed transactions here?

Comment threadsrc/wallet/mod.rs
original_tx,
tx.clone(),
)?;
self.write_broadcast_intent(&replacement_intent)?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

write_broadcast_intent runs before next_broadcast_timestamp. If an existing lineage contains u64::MAX - 1, the timestamp call fails after the new active replacement has been persisted but before BDK records it. Restart then fails while reapplying the missing active transaction. Could we calculate the timestamp before persisting the replacement, or roll the intent back, and add an RBF restart test for this boundary?

Sign up for freeto 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.

On-chain send returns before backend broadcast result

2 participants

@ovitrif@ben-kaufman