Repository navigation
feat: hold a spliced successor's funding transaction until its CET locktime - #238
Open
matthewjablack wants to merge 2 commits into
Open
matthewjablack wants to merge 2 commits into
matthewjablack wants to merge 2 commits into
Conversation
…cktime A new contract_flags bit, FUND_LOCKTIME_AT_CET_FLAG (0x04), gives a spliced contract's funding transaction nLockTime = the offer's CET locktime. ddk-dlc already turns a nonzero funding locktime into sequence 0xfffffffe on every funding input, the DLC input included, so a successor can be signed now and held until then. Contracts without a DLC input, and every splice without the bit, keep locktime 0 and build the same bytes as before. The switch is a flag rather than an argument because the flag already travels on the offer and is stored with the contract: both parties, and a stored contract rebuilt later, get the same transactions. Bit 1 is skipped. The stored OfferedContract reader takes a first byte of 0x02 or 0x03 as a compressed pubkey, so contract_flags 0x02/0x03 would be misread. Offer creation and validation (stateless and Manager) now reject any bit ddk gives no meaning to. The Manager broadcast the funding transaction on sign and returned the error when the network refused it, so a held successor failed as non-final and its replaced contract was never marked as closing. A held funding transaction the network refuses now leaves the contract Signed and the replaced contract Confirmed; the periodic check re-signs it from the stored signatures and broadcasts it once it is final, then pre-closes the replaced contracts.
… signed The Manager treated any broadcast error on a funding transaction with a locktime as a hold, so a final transaction the network refused for a bad witness or a missing input left the contract Signed and returned Ok. It now checks finality itself: a height locktime is final once the tip reaches it, a time locktime once the tip's median time past is beyond it (BIP 113). It skips the broadcast only while the transaction is not final, and every broadcast error after that propagates. Blockchain gains get_median_time_past for that check; EsploraClient reads it from the tip's block info. The accepting party also re-signed the held transaction with its wallet on every periodic check, so a signer that went offline after signing kept the successor from ever being broadcast. It now stores the signed funding transaction when it signs a held successor and broadcasts exactly that.
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.
Summary
Lets a spliced successor contract be signed now and its funding transaction held until a later time.
contract_flagsbitFUND_LOCKTIME_AT_CET_FLAG(0x04). A spliced contract (one with a DLC input) whose offer sets it gets a funding transaction withnLockTime = cet_locktime. ddk-dlc already turns a nonzero funding locktime into sequence0xfffffffeon every funding input, the DLC input included, so nothing below the builder changes.contract_flagsalready travels on the offer and is stored with the contract, so both parties, and a stored contract rebuilt later, get the same bytes.OfferedContractreader treats a first byte of0x02/0x03as a compressed pubkey, socontract_flagsof 0x02 or 0x03 would be misread.ddk::contractand the Manager. The builder does not reject them, so stored contracts still rebuild.Manager
The Manager broadcast the funding transaction on sign and returned the error if it was refused. A held successor was rejected as
non-final, and the contract it replaced was never marked as closing. Now:dlc_transactions.fund. It is the only party with every signature.Signedand the parent staysConfirmed.API addition:
Blockchain::get_median_time_pastis a new required method.EsploraClientreads it from the tip's block info. A default implementation isn't possible:async_traitdefault bodies needSelf: Sync, and the Manager'sB::Targetdoesn't provide it. Any externalBlockchainimplementor will need to add this method.Tests
lock_time == cet_locktime, every input has sequence0xfffffffe, both halves of the DLC input verify, and the txid matches the rebuilt transaction;0x05round-trip on the wire;0x02,0x03,0x06,0x08,0x80) are rejected bycreate_offerandvalidate_offer.0x04/0x05round-trip through both storedOfferedContractformats;0x02/0x03are rejected;is_final_at.stateless_execution::held_splice_broadcasts_at_the_cet_locktime: the node refuses the held funding transaction asnon-finalone block early, accepts the same bytes at the locktime, and the successor settles with a CET.manager_execution_tests::held_splice_enum_single_oracle_test(dual-funded successor):Signedand the parentConfirmeduntil the locktime;EsploraClient's median time past matches bitcoind's.