Repository navigation
fix: replace secp placeholders when merging funding witnesses - #1715
Merged
Merged
Conversation
quake
approved these changes
Oct 29, 2026
LusoCryptoLabs
added a commit
to LusoCryptoLabs/ckb-script-pitfalls
that referenced
this pull request
Oct 29, 2026
as_slice() of a Bytes field carries the four length bytes, so it never equals the content. Seen in nervosnetwork/fiber#1715. Host test with a control.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
merge_external_funding_witnessesis meant to fill our empty or placeholder witnesses from the peer'sTxSignatures.is_empty_or_placeholder_witnesspasseswitness.as_slice()tois_secp_sighash_placeholder_witness, which expects the raw witness.as_slice()of apacked::Bytescarries molecule's 4-byte length header, so the zero-signatureWitnessArgsthe funding builder writes for the peer's secp256k1 inputs is never taken for a placeholder. The initiator keeps the zeros instead of the peer's signature, and its copy of the funding tx fails with-302 TransactionFailedToVerify(secp256k1 lock, error -11). The acceptor's copy is complete and gets the channel open.is_empty_or_placeholder_witnesscheckswitness.raw_data().This is also what #1713 needs to help in practice: with secp256k1 inputs on the acceptor's side, the merged set it replies with still holds the placeholder until this is fixed.
Seen on our testnet LSP (a fork with #1623; this code is the same on develop): openings sent a copy of the funding tx that failed with
-302at the LSP's input, the same size as the copy that was committed. Reproduced on a dev chain through a proxy that keeps everysend_transaction: before the change, the initiator's copy of each opening had a zero signature at the acceptor's input, in both signing orders; after it, every copy was fully signed. With the change on our testnet LSP, the next four openings (two from secp256k1 keys, two from passkey wallets, one of them in a UDT, in both signing orders) sent no copy that failed; with the binary before it, each of the five openings that day did.Checked on this branch:
test_external_funding_witness_merge_replaces_secp_placeholders: a local placeholder takes the peer's signature, and a peer's placeholder does not replace ours. It fails on develop.cargo fmt,typos,cargo shear,make clippycargo test -p fnn --features rocksdb: all pass exceptfiber::tests::mpp::test_mpp_waiting_ack_settlement_hands_off_to_durable_retry_queue, which fails on develop too