input: add weight estimation + tests for all taproot witness gen types
This commit is contained in:
5 files changed
+946
-54
No files matched your search
+268
@@ -153,6 +153,12 @@ const (
|
|||||||
// - PkScript (P2WSH)
|
// - PkScript (P2WSH)
|
||||||
CommitmentDelayOutput = 8 + 1 + P2WSHSize
|
CommitmentDelayOutput = 8 + 1 + P2WSHSize
|
||||||
|
|
||||||
|
// TaprootCommitmentOutput 43 bytes
|
||||||
|
// - Value: 8 bytes
|
||||||
|
// - VarInt: 1 byte (PkScript length)
|
||||||
|
// - PkScript (P2TR)
|
||||||
|
TaprootCommitmentOutput = 8 + 1 + P2TRSize
|
||||||
|
|
||||||
// CommitmentKeyHashOutput 31 bytes
|
// CommitmentKeyHashOutput 31 bytes
|
||||||
// - Value: 8 bytes
|
// - Value: 8 bytes
|
||||||
// - VarInt: 1 byte (PkScript length)
|
// - VarInt: 1 byte (PkScript length)
|
||||||
@@ -165,6 +171,12 @@ const (
|
|||||||
// - PkScript (P2WSH)
|
// - PkScript (P2WSH)
|
||||||
CommitmentAnchorOutput = 8 + 1 + P2WSHSize
|
CommitmentAnchorOutput = 8 + 1 + P2WSHSize
|
||||||
|
|
||||||
|
// TaprootCommitmentAnchorOutput 43 bytes
|
||||||
|
// - Value: 8 bytes
|
||||||
|
// - VarInt: 1 byte (PkScript length)
|
||||||
|
// - PkScript (P2TR)
|
||||||
|
TaprootCommitmentAnchorOutput = 8 + 1 + P2TRSize
|
||||||
|
|
||||||
// HTLCSize 43 bytes
|
// HTLCSize 43 bytes
|
||||||
// - Value: 8 bytes
|
// - Value: 8 bytes
|
||||||
// - VarInt: 1 byte (PkScript length)
|
// - VarInt: 1 byte (PkScript length)
|
||||||
@@ -222,12 +234,32 @@ const (
|
|||||||
// BaseAnchorCommitmentTxWeight 900 weight.
|
// BaseAnchorCommitmentTxWeight 900 weight.
|
||||||
BaseAnchorCommitmentTxWeight = witnessScaleFactor * BaseAnchorCommitmentTxSize
|
BaseAnchorCommitmentTxWeight = witnessScaleFactor * BaseAnchorCommitmentTxSize
|
||||||
|
|
||||||
|
// BaseTaprootCommitmentTxWeight 225 + 43 * num-htlc-outputs bytes
|
||||||
|
// - Version: 4 bytes
|
||||||
|
// - WitnessHeader <---- part of the witness data
|
||||||
|
// - CountTxIn: 1 byte
|
||||||
|
// - TxIn: 41 bytes
|
||||||
|
// FundingInput
|
||||||
|
// - CountTxOut: 3 byte
|
||||||
|
// - TxOut: 172 + 43 * num-htlc-outputs bytes
|
||||||
|
// OutputPayingToThem,
|
||||||
|
// OutputPayingToUs,
|
||||||
|
// ....HTLCOutputs...
|
||||||
|
// - LockTime: 4 bytes
|
||||||
|
BaseTaprootCommitmentTxWeight = (4 + 1 + FundingInputSize + 3 +
|
||||||
|
2*TaprootCommitmentOutput + 2*TaprootCommitmentAnchorOutput + 4) *
|
||||||
|
witnessScaleFactor
|
||||||
|
|
||||||
// CommitWeight 724 weight.
|
// CommitWeight 724 weight.
|
||||||
CommitWeight = BaseCommitmentTxWeight + WitnessCommitmentTxWeight
|
CommitWeight = BaseCommitmentTxWeight + WitnessCommitmentTxWeight
|
||||||
|
|
||||||
// AnchorCommitWeight 1124 weight.
|
// AnchorCommitWeight 1124 weight.
|
||||||
AnchorCommitWeight = BaseAnchorCommitmentTxWeight + WitnessCommitmentTxWeight
|
AnchorCommitWeight = BaseAnchorCommitmentTxWeight + WitnessCommitmentTxWeight
|
||||||
|
|
||||||
|
// TaprootCommitWeight 968 weight.
|
||||||
|
TaprootCommitWeight = (BaseTaprootCommitmentTxWeight +
|
||||||
|
WitnessHeaderSize + TaprootKeyPathWitnessSize)
|
||||||
|
|
||||||
// HTLCWeight 172 weight.
|
// HTLCWeight 172 weight.
|
||||||
HTLCWeight = witnessScaleFactor * HTLCSize
|
HTLCWeight = witnessScaleFactor * HTLCSize
|
||||||
|
|
||||||
@@ -236,11 +268,19 @@ const (
|
|||||||
// which will transition an outgoing HTLC to the delay-and-claim state.
|
// which will transition an outgoing HTLC to the delay-and-claim state.
|
||||||
HtlcTimeoutWeight = 663
|
HtlcTimeoutWeight = 663
|
||||||
|
|
||||||
|
// TaprootHtlcTimeoutWeight is the total weight of the taproot HTLC
|
||||||
|
// timeout transaction.
|
||||||
|
TaprootHtlcTimeoutWeight = 645
|
||||||
|
|
||||||
// HtlcSuccessWeight 703 weight
|
// HtlcSuccessWeight 703 weight
|
||||||
// HtlcSuccessWeight is the weight of the HTLC success transaction
|
// HtlcSuccessWeight is the weight of the HTLC success transaction
|
||||||
// which will transition an incoming HTLC to the delay-and-claim state.
|
// which will transition an incoming HTLC to the delay-and-claim state.
|
||||||
HtlcSuccessWeight = 703
|
HtlcSuccessWeight = 703
|
||||||
|
|
||||||
|
// TaprootHtlcSuccessWeight is the total weight of the taproot HTLC
|
||||||
|
// success transaction.
|
||||||
|
TaprootHtlcSuccessWeight = 705
|
||||||
|
|
||||||
// HtlcConfirmedScriptOverhead 3 bytes
|
// HtlcConfirmedScriptOverhead 3 bytes
|
||||||
// HtlcConfirmedScriptOverhead is the extra length of an HTLC script
|
// HtlcConfirmedScriptOverhead is the extra length of an HTLC script
|
||||||
// that requires confirmation before it can be spent. These extra bytes
|
// that requires confirmation before it can be spent. These extra bytes
|
||||||
@@ -556,6 +596,232 @@ const (
|
|||||||
// - leafVersionAndParity: 1 byte
|
// - leafVersionAndParity: 1 byte
|
||||||
// - schnorrPubKey: 32 byte
|
// - schnorrPubKey: 32 byte
|
||||||
TaprootBaseControlBlockWitnessSize = 33
|
TaprootBaseControlBlockWitnessSize = 33
|
||||||
|
|
||||||
|
// TaprootToLocalScriptSize
|
||||||
|
// - OP_DATA: 1 byte (pub key len)
|
||||||
|
// - local_key: 32 bytes
|
||||||
|
// - OP_CHECKSIG: 1 byte
|
||||||
|
// - OP_DATA: 1 byte (csv delay)
|
||||||
|
// - csv_delay: 4 bytes (worst case estimate)
|
||||||
|
// - OP_CSV: 1 byte
|
||||||
|
// - OP_DROP: 1 byte
|
||||||
|
TaprootToLocalScriptSize = 41
|
||||||
|
|
||||||
|
// TaprootToLocalWitnessSize: 175 bytes
|
||||||
|
// - number_of_witness_elements: 1 byte
|
||||||
|
// - sig_len: 1 byte
|
||||||
|
// - sweep_sig: 65 bytes (worst case w/o sighash default)
|
||||||
|
// - script_len: 1 byte
|
||||||
|
// - taproot_to_local_script_size: 41 bytes
|
||||||
|
// - ctrl_block_len: 1 byte
|
||||||
|
// - base_control_block_size: 33 bytes
|
||||||
|
// - sibling_merkle_hash: 32 bytes
|
||||||
|
TaprootToLocalWitnessSize = 1 + 1 + 65 + 1 + TaprootToLocalScriptSize +
|
||||||
|
1 + TaprootBaseControlBlockWitnessSize + 32
|
||||||
|
|
||||||
|
// TaprootToLocalRevokeScriptSize: 68 bytes
|
||||||
|
// - OP_DATA: 1 byte
|
||||||
|
// - local key: 32 bytes
|
||||||
|
// - OP_DROP: 1 byte
|
||||||
|
// - OP_DATA: 1 byte
|
||||||
|
// - revocation key: 32 bytes
|
||||||
|
// - OP_CHECKSIG: 1 byte
|
||||||
|
TaprootToLocalRevokeScriptSize = 1 + 32 + 1 + 1 + 32 + 1
|
||||||
|
|
||||||
|
// TaprootToLocalRevokeWitnessSize: 202 bytes
|
||||||
|
// - NumberOfWitnessElements: 1 byte
|
||||||
|
// - sigLength: 1 byte
|
||||||
|
// - sweep sig: 65 bytes
|
||||||
|
// - script len: 1 byte
|
||||||
|
// - revocation script size: 68 bytes
|
||||||
|
// - ctrl block size: 1 byte
|
||||||
|
// - base control block: 33 bytes
|
||||||
|
// - merkle proof: 32
|
||||||
|
TaprootToLocalRevokeWitnessSize = 1 + 1 + 65 + 1 + TaprootToLocalRevokeScriptSize + 1 + 33 + 32
|
||||||
|
|
||||||
|
// TaprootToRemoteScriptSize
|
||||||
|
// - OP_DATA: 1 byte
|
||||||
|
// - remote key: 32 bytes
|
||||||
|
// - OP_CHECKSIG: 1 byte
|
||||||
|
// - OP_1: 1 byte
|
||||||
|
// - OP_CHECKSEQUENCEVERIFY: 1 byte
|
||||||
|
// - OP_DROP: 1 byte
|
||||||
|
TaprootToRemoteScriptSize = 1 + 32 + 1 + 1 + 1 + 1
|
||||||
|
|
||||||
|
// TaprootToRemoteWitnessSize:
|
||||||
|
// - number_of_witness_elements: 1 byte
|
||||||
|
// - sig_len: 1 byte
|
||||||
|
// - sweep_sig: 65 bytes (worst case w/o sighash default)
|
||||||
|
// - script_len: 1 byte
|
||||||
|
// - taproot_to_local_script_size: 36 bytes
|
||||||
|
// - ctrl_block_len: 1 byte
|
||||||
|
// - base_control_block_size: 33 bytes
|
||||||
|
TaprootToRemoteWitnessSize = 1 + 1 + 65 + 1 + TaprootToRemoteScriptSize +
|
||||||
|
1 + TaprootBaseControlBlockWitnessSize
|
||||||
|
|
||||||
|
// TaprootAnchorWitnessSize: 67 bytes
|
||||||
|
//
|
||||||
|
// In this case, we use the custom sighash size to give the most
|
||||||
|
// pessemistic estimate.
|
||||||
|
TaprootAnchorWitnessSize = TaprootKeyPathCustomSighashWitnessSize
|
||||||
|
|
||||||
|
// TaprootSecondLevelHtlcScriptSize: 41 bytes
|
||||||
|
// - OP_DATA: 1 byte (pub key len)
|
||||||
|
// - local_key: 32 bytes
|
||||||
|
// - OP_CHECKSIG: 1 byte
|
||||||
|
// - OP_DATA: 1 byte (csv delay)
|
||||||
|
// - csv_delay: 4 bytes (worst case)
|
||||||
|
// - OP_CSV: 1 byte
|
||||||
|
// - OP_DROP: 1 byte
|
||||||
|
TaprootSecondLevelHtlcScriptSize = 1 + 32 + 1 + 1 + 4 + 1 + 1
|
||||||
|
|
||||||
|
// TaprootSecondLevelHtlcWitnessSize:
|
||||||
|
// - number_of_witness_elements: 1 byte
|
||||||
|
// - sig_len: 1 byte
|
||||||
|
// - sweep_sig: 65 bytes (worst case w/o sighash default)
|
||||||
|
// - script_len: 1 byte
|
||||||
|
// - taproot_second_level_htlc_script_size: 40 bytes
|
||||||
|
// - ctrl_block_len: 1 byte
|
||||||
|
// - base_control_block_size: 33 bytes
|
||||||
|
TaprootSecondLevelHtlcWitnessSize = 1 + 1 + 65 + 1 +
|
||||||
|
TaprootSecondLevelHtlcScriptSize + 1 +
|
||||||
|
TaprootBaseControlBlockWitnessSize
|
||||||
|
|
||||||
|
// TaprootSecondLevelRevokeWitnessSize
|
||||||
|
// - number_of_witness_elements: 1 byte
|
||||||
|
// - sig_len: 1 byte
|
||||||
|
// - sweep_sig: 65 bytes (worst case w/o sighash default)
|
||||||
|
TaprootSecondLevelRevokeWitnessSize = TaprootKeyPathCustomSighashWitnessSize
|
||||||
|
|
||||||
|
// TaprootAcceptedRevokeWitnessSize:
|
||||||
|
// - number_of_witness_elements: 1 byte
|
||||||
|
// - sig_len: 1 byte
|
||||||
|
// - sweep_sig: 65 bytes (worst case w/o sighash default)
|
||||||
|
TaprootAcceptedRevokeWitnessSize = TaprootKeyPathCustomSighashWitnessSize
|
||||||
|
|
||||||
|
// TaprootOfferedRevokeWitnessSize:
|
||||||
|
// - number_of_witness_elements: 1 byte
|
||||||
|
// - sig_len: 1 byte
|
||||||
|
// - sweep_sig: 65 bytes (worst case w/o sighash default)
|
||||||
|
TaprootOfferedRevokeWitnessSize = TaprootKeyPathCustomSighashWitnessSize
|
||||||
|
|
||||||
|
// TaprootHtlcOfferedRemoteTimeoutScriptSize: 42 bytes
|
||||||
|
// - OP_DATA: 1 byte (pub key len)
|
||||||
|
// - local_key: 32 bytes
|
||||||
|
// - OP_CHECKSIG: 1 byte
|
||||||
|
// - OP_1: 1 byte
|
||||||
|
// - OP_DROP: 1 byte
|
||||||
|
// - OP_CHECKSEQUENCEVERIFY: 1 byte
|
||||||
|
// - OP_DATA: 1 byte (cltv_expiry length)
|
||||||
|
// - cltv_expiry: 4 bytes
|
||||||
|
// - OP_CHECKLOCKTIMEVERIFY: 1 byte
|
||||||
|
// - OP_DROP: 1 byte
|
||||||
|
TaprootHtlcOfferedRemoteTimeoutScriptSize = 1 + 32 + 1 + 1 + 1 + 1 + 1 + 4 + 1 + 1
|
||||||
|
|
||||||
|
// TaprootHtlcOfferedRemoteTimeoutwitSize: 176 bytes
|
||||||
|
// - number_of_witness_elements: 1 byte
|
||||||
|
// - sig_len: 1 byte
|
||||||
|
// - sweep_sig: 65 bytes (worst case w/o sighash default)
|
||||||
|
// - script_len: 1 byte
|
||||||
|
// - taproot_offered_htlc_script_size: 42 bytes
|
||||||
|
// - ctrl_block_len: 1 byte
|
||||||
|
// - base_control_block_size: 33 bytes
|
||||||
|
// - sibilng_merkle_proof: 32 bytes
|
||||||
|
TaprootHtlcOfferedRemoteTimeoutWitnessSize = 1 + 1 + 65 + 1 +
|
||||||
|
TaprootHtlcOfferedRemoteTimeoutScriptSize + 1 +
|
||||||
|
TaprootBaseControlBlockWitnessSize + 32
|
||||||
|
|
||||||
|
// TaprootHtlcOfferedLocalTmeoutScriptSize:
|
||||||
|
// - OP_DATA: 1 byte (pub key len)
|
||||||
|
// - local_key: 32 bytes
|
||||||
|
// - OP_CHECKSIGVERIFY: 1 byte
|
||||||
|
// - OP_DATA: 1 byte (pub key len)
|
||||||
|
// - remote_key: 32 bytes
|
||||||
|
// - OP_CHECKSIG: 1 byte
|
||||||
|
TaprootHtlcOfferedLocalTimeoutScriptSize = 1 + 32 + 1 + 1 + 32 + 1
|
||||||
|
|
||||||
|
// TaprootOfferedLocalTimeoutWitnessSize
|
||||||
|
// - number_of_witness_elements: 1 byte
|
||||||
|
// - sig_len: 1 byte
|
||||||
|
// - sweep_sig: 65 bytes (worst case w/o sighash default)
|
||||||
|
// - sig_len: 1 byte
|
||||||
|
// - sweep_sig: 65 bytes (worst case w/o sighash default)
|
||||||
|
// - script_len: 1 byte
|
||||||
|
// - taproot_offered_htlc_script_timeout_size:
|
||||||
|
// - ctrl_block_len: 1 byte
|
||||||
|
// - base_control_block_size: 33 bytes
|
||||||
|
// - sibilng_merkle_proof: 32 bytes
|
||||||
|
TaprootOfferedLocalTimeoutWitnessSize = 1 + 1 + 65 + 1 + 65 + 1 +
|
||||||
|
TaprootHtlcOfferedLocalTimeoutScriptSize + 1 +
|
||||||
|
TaprootBaseControlBlockWitnessSize + 32
|
||||||
|
|
||||||
|
// TaprootHtlcAcceptedRemoteSuccessScriptSize:
|
||||||
|
// - OP_SIZE: 1 byte
|
||||||
|
// - OP_DATA: 1 byte
|
||||||
|
// - 32: 1 byte
|
||||||
|
// - OP_EQUALVERIFY: 1 byte
|
||||||
|
// - OP_HASH160: 1 byte
|
||||||
|
// - OP_DATA: 1 byte (RIPEMD160(payment_hash) length)
|
||||||
|
// - RIPEMD160(payment_hash): 20 bytes
|
||||||
|
// - OP_EQUALVERIFY: 1 byte
|
||||||
|
// - OP_DATA: 1 byte (pub key len)
|
||||||
|
// - remote_key: 32 bytes
|
||||||
|
// - OP_CHECKSIG: 1 byte
|
||||||
|
// - OP_1: 1 byte
|
||||||
|
// - OP_CSV: 1 byte
|
||||||
|
// - OP_DROP: 1 byte
|
||||||
|
TaprootHtlcAcceptedRemoteSuccessScriptSize = 1 + 1 + 1 + 1 + 1 + 1 +
|
||||||
|
1 + 20 + 1 + 32 + 1 + 1 + 1 + 1
|
||||||
|
|
||||||
|
// TaprootHtlcAcceptedRemoteSuccessScriptSize:
|
||||||
|
// - number_of_witness_elements: 1 byte
|
||||||
|
// - sig_len: 1 byte
|
||||||
|
// - sweep_sig: 65 bytes (worst case w/o sighash default)
|
||||||
|
// - payment_preimage_length: 1 byte
|
||||||
|
// - payment_preimage: 32 bytes
|
||||||
|
// - script_len: 1 byte
|
||||||
|
// - taproot_offered_htlc_script_success_size:
|
||||||
|
// - ctrl_block_len: 1 byte
|
||||||
|
// - base_control_block_size: 33 bytes
|
||||||
|
// - sibilng_merkle_proof: 32 bytes
|
||||||
|
TaprootHtlcAcceptedRemoteSuccessWitnessSize = 1 + 1 + 65 + 1 + 32 + 1 +
|
||||||
|
TaprootHtlcAcceptedRemoteSuccessScriptSize + 1 +
|
||||||
|
TaprootBaseControlBlockWitnessSize + 32
|
||||||
|
|
||||||
|
// TaprootHtlcAcceptedLocalSuccessScriptSize:
|
||||||
|
// - OP_SIZE: 1 byte
|
||||||
|
// - OP_DATA: 1 byte
|
||||||
|
// - 32: 1 byte
|
||||||
|
// - OP_EQUALVERIFY: 1 byte
|
||||||
|
// - OP_HASH160: 1 byte
|
||||||
|
// - OP_DATA: 1 byte (RIPEMD160(payment_hash) length)
|
||||||
|
// - RIPEMD160(payment_hash): 20 bytes
|
||||||
|
// - OP_EQUALVERIFY: 1 byte
|
||||||
|
// - OP_DATA: 1 byte (pub key len)
|
||||||
|
// - local_key: 32 bytes
|
||||||
|
// - OP_CHECKSIGVERIFY: 1 byte
|
||||||
|
// - OP_DATA: 1 byte (pub key len)
|
||||||
|
// - remote_key: 32 bytes
|
||||||
|
// - OP_CHECKSIG: 1 byte
|
||||||
|
TaprootHtlcAcceptedLocalSuccessScriptSize = 1 + 1 + 1 + 1 + 1 + 1 +
|
||||||
|
20 + 1 + 1 + 32 + 1 + 1 + 32 + 1
|
||||||
|
|
||||||
|
// TaprootHtlcAcceptedLocalSuccessWitnessSize:
|
||||||
|
// - number_of_witness_elements: 1 byte
|
||||||
|
// - sig_len: 1 byte
|
||||||
|
// - sweep_sig: 65 bytes (worst case w/o sighash default)
|
||||||
|
// - sig_len: 1 byte
|
||||||
|
// - sweep_sig: 65 bytes (worst case w/o sighash default)
|
||||||
|
// - payment_preimage_length: 1 byte
|
||||||
|
// - payment_preimage: 32 bytes
|
||||||
|
// - script_len: 1 byte
|
||||||
|
// - taproot_accepted_htlc_script_success_size:
|
||||||
|
// - ctrl_block_len: 1 byte
|
||||||
|
// - base_control_block_size: 33 bytes
|
||||||
|
// - sibilng_merkle_proof: 32 bytes
|
||||||
|
TaprootHtlcAcceptedLocalSuccessWitnessSize = 1 + 1 + 65 + 1 + 65 + 1 +
|
||||||
|
32 + 1 + TaprootHtlcAcceptedLocalSuccessScriptSize + 1 +
|
||||||
|
TaprootBaseControlBlockWitnessSize + 32
|
||||||
)
|
)
|
||||||
|
|
||||||
// EstimateCommitTxWeight estimate commitment transaction weight depending on
|
// EstimateCommitTxWeight estimate commitment transaction weight depending on
|
||||||
@@ -572,6 +838,8 @@ func EstimateCommitTxWeight(count int, prediction bool) int64 {
|
|||||||
baseWeight := int64(BaseCommitmentTxWeight)
|
baseWeight := int64(BaseCommitmentTxWeight)
|
||||||
witnessWeight := int64(WitnessCommitmentTxWeight)
|
witnessWeight := int64(WitnessCommitmentTxWeight)
|
||||||
|
|
||||||
|
// TODO(roasbeef): need taproot modifier? also no anchor so wrong?
|
||||||
|
|
||||||
return htlcWeight + baseWeight + witnessWeight
|
return htlcWeight + baseWeight + witnessWeight
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+623
-47
@@ -26,6 +26,10 @@ const (
|
|||||||
// without the trailing sighash flag.
|
// without the trailing sighash flag.
|
||||||
maxDERSignatureSize = 72
|
maxDERSignatureSize = 72
|
||||||
|
|
||||||
|
// maxSchnorrSignature is the largest possilbe schnorr sig w/o a non
|
||||||
|
// default sighash.
|
||||||
|
maxSchnorrSignatureSize = 64
|
||||||
|
|
||||||
testAmt = btcutil.MaxSatoshi
|
testAmt = btcutil.MaxSatoshi
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -313,6 +317,18 @@ func (s *maxDERSignature) Verify(_ []byte, _ *btcec.PublicKey) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type maxSchnorrSignature struct{}
|
||||||
|
|
||||||
|
func (s *maxSchnorrSignature) Serialize() []byte {
|
||||||
|
// Always return worst-case signature length, including a non-default
|
||||||
|
// sighash type.
|
||||||
|
return make([]byte, maxSchnorrSignatureSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *maxSchnorrSignature) Verify(_ []byte, _ *btcec.PublicKey) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// dummySigner is a fake signer used for size (upper bound) calculations.
|
// dummySigner is a fake signer used for size (upper bound) calculations.
|
||||||
type dummySigner struct {
|
type dummySigner struct {
|
||||||
input.Signer
|
input.Signer
|
||||||
@@ -323,6 +339,15 @@ type dummySigner struct {
|
|||||||
func (s *dummySigner) SignOutputRaw(tx *wire.MsgTx,
|
func (s *dummySigner) SignOutputRaw(tx *wire.MsgTx,
|
||||||
signDesc *input.SignDescriptor) (input.Signature, error) {
|
signDesc *input.SignDescriptor) (input.Signature, error) {
|
||||||
|
|
||||||
|
switch signDesc.SignMethod {
|
||||||
|
case input.TaprootKeySpendBIP0086SignMethod:
|
||||||
|
fallthrough
|
||||||
|
case input.TaprootKeySpendSignMethod:
|
||||||
|
fallthrough
|
||||||
|
case input.TaprootScriptSpendSignMethod:
|
||||||
|
return &maxSchnorrSignature{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
return &maxDERSignature{}, nil
|
return &maxDERSignature{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -813,6 +838,494 @@ var witnessSizeTests = []witnessSizeTest{
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return witness
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "taproot to local sweep",
|
||||||
|
expSize: input.TaprootToLocalWitnessSize,
|
||||||
|
genWitness: func(t *testing.T) wire.TxWitness {
|
||||||
|
testKey, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
signer := &dummySigner{}
|
||||||
|
commitScriptTree, err := input.NewLocalCommitScriptTree(
|
||||||
|
testCSVDelay, testKey.PubKey(), testKey.PubKey(),
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
signDesc := &input.SignDescriptor{
|
||||||
|
KeyDesc: keychain.KeyDescriptor{
|
||||||
|
PubKey: testKey.PubKey(),
|
||||||
|
},
|
||||||
|
WitnessScript: commitScriptTree.SettleLeaf.Script,
|
||||||
|
HashType: txscript.SigHashAll,
|
||||||
|
InputIndex: 0,
|
||||||
|
SignMethod: input.TaprootScriptSpendSignMethod,
|
||||||
|
}
|
||||||
|
|
||||||
|
witness, err := input.TaprootCommitSpendSuccess(
|
||||||
|
signer, signDesc, testTx,
|
||||||
|
commitScriptTree.TapscriptTree,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
return witness
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "taproot to local revocation",
|
||||||
|
expSize: input.TaprootToLocalRevokeWitnessSize,
|
||||||
|
genWitness: func(t *testing.T) wire.TxWitness {
|
||||||
|
testKey, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
signer := &dummySigner{}
|
||||||
|
commitScriptTree, err := input.NewLocalCommitScriptTree(
|
||||||
|
testCSVDelay, testKey.PubKey(), testKey.PubKey(),
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
signDesc := &input.SignDescriptor{
|
||||||
|
KeyDesc: keychain.KeyDescriptor{
|
||||||
|
PubKey: testKey.PubKey(),
|
||||||
|
},
|
||||||
|
WitnessScript: commitScriptTree.RevocationLeaf.Script,
|
||||||
|
HashType: txscript.SigHashAll,
|
||||||
|
InputIndex: 0,
|
||||||
|
SignMethod: input.TaprootScriptSpendSignMethod,
|
||||||
|
}
|
||||||
|
|
||||||
|
witness, err := input.TaprootCommitSpendRevoke(
|
||||||
|
signer, signDesc, testTx,
|
||||||
|
commitScriptTree.TapscriptTree,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
return witness
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "taproot to remote sweep",
|
||||||
|
expSize: input.TaprootToRemoteWitnessSize,
|
||||||
|
genWitness: func(t *testing.T) wire.TxWitness {
|
||||||
|
testKey, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
signer := &dummySigner{}
|
||||||
|
commitScriptTree, err := input.NewRemoteCommitScriptTree(
|
||||||
|
testKey.PubKey(),
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
signDesc := &input.SignDescriptor{
|
||||||
|
KeyDesc: keychain.KeyDescriptor{
|
||||||
|
PubKey: testKey.PubKey(),
|
||||||
|
},
|
||||||
|
WitnessScript: commitScriptTree.SettleLeaf.Script,
|
||||||
|
HashType: txscript.SigHashAll,
|
||||||
|
InputIndex: 0,
|
||||||
|
SignMethod: input.TaprootScriptSpendSignMethod,
|
||||||
|
}
|
||||||
|
|
||||||
|
witness, err := input.TaprootCommitRemoteSpend(
|
||||||
|
signer, signDesc, testTx,
|
||||||
|
commitScriptTree.TapscriptTree,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
return witness
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "taproot anchor sweep",
|
||||||
|
expSize: input.TaprootAnchorWitnessSize,
|
||||||
|
genWitness: func(t *testing.T) wire.TxWitness {
|
||||||
|
testKey, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
signer := &dummySigner{}
|
||||||
|
|
||||||
|
anchorScriptTree, err := input.NewAnchorScriptTree(
|
||||||
|
testKey.PubKey(),
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
signDesc := &input.SignDescriptor{
|
||||||
|
KeyDesc: keychain.KeyDescriptor{
|
||||||
|
PubKey: testKey.PubKey(),
|
||||||
|
},
|
||||||
|
HashType: txscript.SigHashAll,
|
||||||
|
InputIndex: 0,
|
||||||
|
SignMethod: input.TaprootKeySpendSignMethod,
|
||||||
|
TapTweak: anchorScriptTree.TapscriptRoot,
|
||||||
|
}
|
||||||
|
|
||||||
|
witness, err := input.TaprootAnchorSpend(
|
||||||
|
signer, signDesc, testTx,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
return witness
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "taproot second level htlc success+timeout",
|
||||||
|
expSize: input.TaprootSecondLevelHtlcWitnessSize,
|
||||||
|
genWitness: func(t *testing.T) wire.TxWitness {
|
||||||
|
testKey, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
signer := &dummySigner{}
|
||||||
|
|
||||||
|
scriptTree, err := input.SecondLevelHtlcTapscriptTree(
|
||||||
|
testKey.PubKey(), testCSVDelay,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
tapScriptRoot := scriptTree.RootNode.TapHash()
|
||||||
|
|
||||||
|
revokeKey, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
tapLeaf := scriptTree.LeafMerkleProofs[0].TapLeaf
|
||||||
|
witnessScript := tapLeaf.Script
|
||||||
|
signDesc := &input.SignDescriptor{
|
||||||
|
KeyDesc: keychain.KeyDescriptor{
|
||||||
|
PubKey: revokeKey.PubKey(),
|
||||||
|
},
|
||||||
|
WitnessScript: witnessScript,
|
||||||
|
HashType: txscript.SigHashAll,
|
||||||
|
InputIndex: 0,
|
||||||
|
SignMethod: input.TaprootKeySpendSignMethod,
|
||||||
|
TapTweak: tapScriptRoot[:],
|
||||||
|
}
|
||||||
|
|
||||||
|
witness, err := input.TaprootHtlcSpendSuccess(
|
||||||
|
signer, signDesc, revokeKey.PubKey(), testTx,
|
||||||
|
scriptTree,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
return witness
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "taproot second level htlc revoke",
|
||||||
|
expSize: input.TaprootSecondLevelRevokeWitnessSize,
|
||||||
|
genWitness: func(t *testing.T) wire.TxWitness {
|
||||||
|
testKey, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
scriptTree, err := input.SecondLevelHtlcTapscriptTree(
|
||||||
|
testKey.PubKey(), testCSVDelay,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
revokeKey, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
signer := &dummySigner{}
|
||||||
|
|
||||||
|
tapScriptRoot := scriptTree.RootNode.TapHash()
|
||||||
|
|
||||||
|
signDesc := &input.SignDescriptor{
|
||||||
|
KeyDesc: keychain.KeyDescriptor{
|
||||||
|
PubKey: revokeKey.PubKey(),
|
||||||
|
},
|
||||||
|
HashType: txscript.SigHashAll,
|
||||||
|
InputIndex: 0,
|
||||||
|
SignMethod: input.TaprootKeySpendSignMethod,
|
||||||
|
TapTweak: tapScriptRoot[:],
|
||||||
|
}
|
||||||
|
|
||||||
|
witness, err := input.TaprootHtlcSpendRevoke(
|
||||||
|
signer, signDesc, testTx,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
return witness
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "taproot offered htlc revoke",
|
||||||
|
expSize: input.TaprootOfferedRevokeWitnessSize,
|
||||||
|
genWitness: func(t *testing.T) wire.TxWitness {
|
||||||
|
senderKey, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
receiverKey, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
revokeKey, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var payHash [32]byte
|
||||||
|
|
||||||
|
signer := &dummySigner{}
|
||||||
|
|
||||||
|
htlcScriptTree, err := input.SenderHTLCScriptTaproot(
|
||||||
|
senderKey.PubKey(), receiverKey.PubKey(),
|
||||||
|
revokeKey.PubKey(), payHash[:],
|
||||||
|
)
|
||||||
|
|
||||||
|
signDesc := &input.SignDescriptor{
|
||||||
|
KeyDesc: keychain.KeyDescriptor{
|
||||||
|
PubKey: revokeKey.PubKey(),
|
||||||
|
},
|
||||||
|
HashType: txscript.SigHashAll,
|
||||||
|
InputIndex: 0,
|
||||||
|
SignMethod: input.TaprootKeySpendSignMethod,
|
||||||
|
TapTweak: htlcScriptTree.TapscriptRoot,
|
||||||
|
}
|
||||||
|
|
||||||
|
witness, err := input.SenderHTLCScriptTaprootRevoke(
|
||||||
|
signer, signDesc, testTx,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
return witness
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "taproot accepted htlc revoke",
|
||||||
|
expSize: input.TaprootAcceptedRevokeWitnessSize,
|
||||||
|
genWitness: func(t *testing.T) wire.TxWitness {
|
||||||
|
senderKey, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
receiverKey, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
revokeKey, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var payHash [32]byte
|
||||||
|
|
||||||
|
signer := &dummySigner{}
|
||||||
|
|
||||||
|
htlcScriptTree, err := input.ReceiverHTLCScriptTaproot(
|
||||||
|
testCLTVExpiry, senderKey.PubKey(),
|
||||||
|
receiverKey.PubKey(), revokeKey.PubKey(),
|
||||||
|
payHash[:],
|
||||||
|
)
|
||||||
|
|
||||||
|
signDesc := &input.SignDescriptor{
|
||||||
|
KeyDesc: keychain.KeyDescriptor{
|
||||||
|
PubKey: revokeKey.PubKey(),
|
||||||
|
},
|
||||||
|
HashType: txscript.SigHashAll,
|
||||||
|
InputIndex: 0,
|
||||||
|
SignMethod: input.TaprootKeySpendSignMethod,
|
||||||
|
TapTweak: htlcScriptTree.TapscriptRoot,
|
||||||
|
}
|
||||||
|
|
||||||
|
witness, err := input.ReceiverHTLCScriptTaprootRevoke(
|
||||||
|
signer, signDesc, testTx,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
return witness
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "taproot offered remote timeout",
|
||||||
|
expSize: input.TaprootHtlcOfferedRemoteTimeoutWitnessSize,
|
||||||
|
genWitness: func(t *testing.T) wire.TxWitness {
|
||||||
|
senderKey, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
receiverKey, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
revokeKey, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var payHash [32]byte
|
||||||
|
|
||||||
|
signer := &dummySigner{}
|
||||||
|
|
||||||
|
htlcScriptTree, err := input.ReceiverHTLCScriptTaproot(
|
||||||
|
testCLTVExpiry, senderKey.PubKey(),
|
||||||
|
receiverKey.PubKey(), revokeKey.PubKey(),
|
||||||
|
payHash[:],
|
||||||
|
)
|
||||||
|
|
||||||
|
timeoutLeaf := htlcScriptTree.TimeoutTapLeaf
|
||||||
|
|
||||||
|
signDesc := &input.SignDescriptor{
|
||||||
|
KeyDesc: keychain.KeyDescriptor{
|
||||||
|
PubKey: senderKey.PubKey(),
|
||||||
|
},
|
||||||
|
WitnessScript: timeoutLeaf.Script,
|
||||||
|
HashType: txscript.SigHashAll,
|
||||||
|
InputIndex: 0,
|
||||||
|
SignMethod: input.TaprootScriptSpendSignMethod,
|
||||||
|
}
|
||||||
|
|
||||||
|
witness, err := input.ReceiverHTLCScriptTaprootTimeout(
|
||||||
|
signer, signDesc, testTx, testCLTVExpiry,
|
||||||
|
revokeKey.PubKey(), htlcScriptTree.TapscriptTree,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
return witness
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "taproot offered local timeout",
|
||||||
|
expSize: input.TaprootOfferedLocalTimeoutWitnessSize,
|
||||||
|
genWitness: func(t *testing.T) wire.TxWitness {
|
||||||
|
|
||||||
|
senderKey, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
receiverKey, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
revokeKey, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var payHash [32]byte
|
||||||
|
|
||||||
|
signer := &dummySigner{}
|
||||||
|
|
||||||
|
htlcScriptTree, err := input.SenderHTLCScriptTaproot(
|
||||||
|
senderKey.PubKey(), receiverKey.PubKey(),
|
||||||
|
revokeKey.PubKey(), payHash[:],
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
timeoutLeaf := htlcScriptTree.TimeoutTapLeaf
|
||||||
|
scriptTree := htlcScriptTree.TapscriptTree
|
||||||
|
|
||||||
|
receiverDesc := &input.SignDescriptor{
|
||||||
|
KeyDesc: keychain.KeyDescriptor{
|
||||||
|
PubKey: receiverKey.PubKey(),
|
||||||
|
},
|
||||||
|
WitnessScript: timeoutLeaf.Script,
|
||||||
|
HashType: txscript.SigHashAll,
|
||||||
|
InputIndex: 0,
|
||||||
|
SignMethod: input.TaprootScriptSpendSignMethod,
|
||||||
|
}
|
||||||
|
receiverSig, err := signer.SignOutputRaw(
|
||||||
|
testTx, receiverDesc,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
signDesc := &input.SignDescriptor{
|
||||||
|
KeyDesc: keychain.KeyDescriptor{
|
||||||
|
PubKey: senderKey.PubKey(),
|
||||||
|
},
|
||||||
|
WitnessScript: timeoutLeaf.Script,
|
||||||
|
HashType: txscript.SigHashAll,
|
||||||
|
InputIndex: 0,
|
||||||
|
SignMethod: input.TaprootScriptSpendSignMethod,
|
||||||
|
}
|
||||||
|
|
||||||
|
witness, err := input.SenderHTLCScriptTaprootTimeout(
|
||||||
|
receiverSig, txscript.SigHashAll, signer,
|
||||||
|
signDesc, testTx, revokeKey.PubKey(),
|
||||||
|
scriptTree,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
return witness
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "taproot accepted remote success",
|
||||||
|
expSize: input.TaprootHtlcAcceptedRemoteSuccessWitnessSize,
|
||||||
|
genWitness: func(t *testing.T) wire.TxWitness {
|
||||||
|
senderKey, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
receiverKey, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
revokeKey, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var payHash [32]byte
|
||||||
|
|
||||||
|
signer := &dummySigner{}
|
||||||
|
|
||||||
|
htlcScriptTree, err := input.SenderHTLCScriptTaproot(
|
||||||
|
senderKey.PubKey(), receiverKey.PubKey(),
|
||||||
|
revokeKey.PubKey(),
|
||||||
|
payHash[:],
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
successLeaf := htlcScriptTree.SuccessTapLeaf
|
||||||
|
scriptTree := htlcScriptTree.TapscriptTree
|
||||||
|
|
||||||
|
signDesc := &input.SignDescriptor{
|
||||||
|
KeyDesc: keychain.KeyDescriptor{
|
||||||
|
PubKey: receiverKey.PubKey(),
|
||||||
|
},
|
||||||
|
WitnessScript: successLeaf.Script,
|
||||||
|
HashType: txscript.SigHashAll,
|
||||||
|
InputIndex: 0,
|
||||||
|
SignMethod: input.TaprootScriptSpendSignMethod,
|
||||||
|
}
|
||||||
|
|
||||||
|
witness, err := input.SenderHTLCScriptTaprootRedeem(
|
||||||
|
signer, signDesc, testTx, testPreimage,
|
||||||
|
revokeKey.PubKey(), scriptTree,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
return witness
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "taproot accepted local success",
|
||||||
|
expSize: input.TaprootHtlcAcceptedLocalSuccessWitnessSize,
|
||||||
|
genWitness: func(t *testing.T) wire.TxWitness {
|
||||||
|
senderKey, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
receiverKey, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
revokeKey, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var payHash [32]byte
|
||||||
|
|
||||||
|
signer := &dummySigner{}
|
||||||
|
|
||||||
|
htlcScriptTree, err := input.ReceiverHTLCScriptTaproot(
|
||||||
|
testCLTVExpiry, senderKey.PubKey(),
|
||||||
|
receiverKey.PubKey(), revokeKey.PubKey(),
|
||||||
|
payHash[:],
|
||||||
|
)
|
||||||
|
|
||||||
|
successsLeaf := htlcScriptTree.SuccessTapLeaf
|
||||||
|
scriptTree := htlcScriptTree.TapscriptTree
|
||||||
|
|
||||||
|
senderDesc := &input.SignDescriptor{
|
||||||
|
KeyDesc: keychain.KeyDescriptor{
|
||||||
|
PubKey: senderKey.PubKey(),
|
||||||
|
},
|
||||||
|
WitnessScript: successsLeaf.Script,
|
||||||
|
HashType: txscript.SigHashAll,
|
||||||
|
InputIndex: 0,
|
||||||
|
SignMethod: input.TaprootScriptSpendSignMethod,
|
||||||
|
}
|
||||||
|
senderSig, err := signer.SignOutputRaw(
|
||||||
|
testTx, senderDesc,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
signDesc := &input.SignDescriptor{
|
||||||
|
KeyDesc: keychain.KeyDescriptor{
|
||||||
|
PubKey: receiverKey.PubKey(),
|
||||||
|
},
|
||||||
|
WitnessScript: successsLeaf.Script,
|
||||||
|
HashType: txscript.SigHashAll,
|
||||||
|
InputIndex: 0,
|
||||||
|
SignMethod: input.TaprootScriptSpendSignMethod,
|
||||||
|
}
|
||||||
|
|
||||||
|
witness, err := input.ReceiverHTLCScriptTaprootRedeem(
|
||||||
|
senderSig, txscript.SigHashAll, testPreimage,
|
||||||
|
signer, signDesc, testTx, revokeKey.PubKey(),
|
||||||
|
scriptTree,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
return witness
|
return witness
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -837,24 +1350,40 @@ func TestWitnessSizes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// genTimeoutTx creates a signed HTLC second level timeout tx.
|
// genTimeoutTx creates a signed HTLC second level timeout tx.
|
||||||
func genTimeoutTx(chanType channeldb.ChannelType) (*wire.MsgTx, error) {
|
func genTimeoutTx(t *testing.T,
|
||||||
|
chanType channeldb.ChannelType) *wire.MsgTx {
|
||||||
|
|
||||||
|
testKeyPriv, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
testPubkey := testKeyPriv.PubKey()
|
||||||
|
|
||||||
// Create the unsigned timeout tx.
|
// Create the unsigned timeout tx.
|
||||||
timeoutTx, err := lnwallet.CreateHtlcTimeoutTx(
|
timeoutTx, err := lnwallet.CreateHtlcTimeoutTx(
|
||||||
chanType, false, testOutPoint, testAmt, testCLTVExpiry,
|
chanType, false, testOutPoint, testAmt, testCLTVExpiry,
|
||||||
testCSVDelay, 0, testPubkey, testPubkey,
|
testCSVDelay, 0, testPubkey, testPubkey,
|
||||||
)
|
)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// In order to sign the transcation, generate the script for the output
|
// In order to sign the transaction, generate the script for the output
|
||||||
// it spends.
|
// it spends.
|
||||||
witScript, err := input.SenderHTLCScript(
|
var (
|
||||||
|
witScript []byte
|
||||||
|
tapscriptTree *input.HtlcScriptTree
|
||||||
|
)
|
||||||
|
if chanType.IsTaproot() {
|
||||||
|
tapscriptTree, err = input.SenderHTLCScriptTaproot(
|
||||||
|
testPubkey, testPubkey, testPubkey, testHash160,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
witScript = tapscriptTree.TimeoutTapLeaf.Script
|
||||||
|
} else {
|
||||||
|
witScript, err = input.SenderHTLCScript(
|
||||||
testPubkey, testPubkey, testPubkey, testHash160,
|
testPubkey, testPubkey, testPubkey, testHash160,
|
||||||
chanType.HasAnchors(),
|
chanType.HasAnchors(),
|
||||||
)
|
)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
signDesc := &input.SignDescriptor{
|
signDesc := &input.SignDescriptor{
|
||||||
@@ -864,39 +1393,66 @@ func genTimeoutTx(chanType channeldb.ChannelType) (*wire.MsgTx, error) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sign the timeout tx and add the witness.
|
|
||||||
sigHashType := lnwallet.HtlcSigHashType(chanType)
|
sigHashType := lnwallet.HtlcSigHashType(chanType)
|
||||||
timeoutWitness, err := input.SenderHtlcSpendTimeout(
|
|
||||||
|
// Sign the timeout tx and add the witness.
|
||||||
|
var timeoutWitness [][]byte
|
||||||
|
|
||||||
|
if chanType.IsTaproot() {
|
||||||
|
signDesc.SignMethod = input.TaprootScriptSpendSignMethod
|
||||||
|
|
||||||
|
timeoutWitness, err = input.SenderHTLCScriptTaprootTimeout(
|
||||||
|
&maxSchnorrSignature{}, sigHashType, &dummySigner{},
|
||||||
|
signDesc, timeoutTx, testPubkey,
|
||||||
|
tapscriptTree.TapscriptTree,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
} else {
|
||||||
|
timeoutWitness, err = input.SenderHtlcSpendTimeout(
|
||||||
&maxDERSignature{}, sigHashType, &dummySigner{},
|
&maxDERSignature{}, sigHashType, &dummySigner{},
|
||||||
signDesc, timeoutTx,
|
signDesc, timeoutTx,
|
||||||
)
|
)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
timeoutTx.TxIn[0].Witness = timeoutWitness
|
timeoutTx.TxIn[0].Witness = timeoutWitness
|
||||||
|
|
||||||
return timeoutTx, nil
|
return timeoutTx
|
||||||
}
|
}
|
||||||
|
|
||||||
// genSuccessTx creates a signed HTLC second level success tx.
|
// genSuccessTx creates a signed HTLC second level success tx.
|
||||||
func genSuccessTx(chanType channeldb.ChannelType) (*wire.MsgTx, error) {
|
func genSuccessTx(t *testing.T, chanType channeldb.ChannelType) *wire.MsgTx {
|
||||||
// Create the unisgned success tx.
|
testKeyPriv, err := btcec.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
testPubkey := testKeyPriv.PubKey()
|
||||||
|
|
||||||
|
// Create the unsigned success tx.
|
||||||
successTx, err := lnwallet.CreateHtlcSuccessTx(
|
successTx, err := lnwallet.CreateHtlcSuccessTx(
|
||||||
chanType, false, testOutPoint, testAmt, testCSVDelay, 0,
|
chanType, false, testOutPoint, testAmt, testCSVDelay, 0,
|
||||||
testPubkey, testPubkey,
|
testPubkey, testPubkey,
|
||||||
)
|
)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// In order to sign the transcation, generate the script for the output
|
// In order to sign the transaction, generate the script for the output
|
||||||
// it spends.
|
// it spends.
|
||||||
witScript, err := input.ReceiverHTLCScript(
|
var (
|
||||||
|
witScript []byte
|
||||||
|
tapscriptTree *input.HtlcScriptTree
|
||||||
|
)
|
||||||
|
if chanType.IsTaproot() {
|
||||||
|
tapscriptTree, err = input.ReceiverHTLCScriptTaproot(
|
||||||
|
testCLTVExpiry, testPubkey, testPubkey, testPubkey,
|
||||||
|
testHash160,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
witScript = tapscriptTree.SuccessTapLeaf.Script
|
||||||
|
} else {
|
||||||
|
witScript, err = input.ReceiverHTLCScript(
|
||||||
testCLTVExpiry, testPubkey, testPubkey,
|
testCLTVExpiry, testPubkey, testPubkey,
|
||||||
testPubkey, testHash160, chanType.HasAnchors(),
|
testPubkey, testHash160, chanType.HasAnchors(),
|
||||||
)
|
)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
signDesc := &input.SignDescriptor{
|
signDesc := &input.SignDescriptor{
|
||||||
@@ -906,18 +1462,31 @@ func genSuccessTx(chanType channeldb.ChannelType) (*wire.MsgTx, error) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sign the success tx and add the witness.
|
|
||||||
sigHashType := lnwallet.HtlcSigHashType(channeldb.SingleFunderBit)
|
sigHashType := lnwallet.HtlcSigHashType(channeldb.SingleFunderBit)
|
||||||
successWitness, err := input.ReceiverHtlcSpendRedeem(
|
|
||||||
|
var successWitness [][]byte
|
||||||
|
|
||||||
|
// Sign the success tx and add the witness.
|
||||||
|
if chanType.IsTaproot() {
|
||||||
|
signDesc.SignMethod = input.TaprootScriptSpendSignMethod
|
||||||
|
|
||||||
|
successWitness, err = input.ReceiverHTLCScriptTaprootRedeem(
|
||||||
|
&maxSchnorrSignature{}, sigHashType, testPreimage,
|
||||||
|
&dummySigner{}, signDesc, successTx, testPubkey,
|
||||||
|
tapscriptTree.TapscriptTree,
|
||||||
|
)
|
||||||
|
require.NoError(t, err)
|
||||||
|
} else {
|
||||||
|
successWitness, err = input.ReceiverHtlcSpendRedeem(
|
||||||
&maxDERSignature{}, sigHashType, testPreimage,
|
&maxDERSignature{}, sigHashType, testPreimage,
|
||||||
&dummySigner{}, signDesc, successTx,
|
&dummySigner{}, signDesc, successTx,
|
||||||
)
|
)
|
||||||
if err != nil {
|
require.NoError(t, err)
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
successTx.TxIn[0].Witness = successWitness
|
successTx.TxIn[0].Witness = successWitness
|
||||||
|
|
||||||
return successTx, nil
|
return successTx
|
||||||
}
|
}
|
||||||
|
|
||||||
type txSizeTest struct {
|
type txSizeTest struct {
|
||||||
@@ -928,36 +1497,35 @@ type txSizeTest struct {
|
|||||||
|
|
||||||
var txSizeTests = []txSizeTest{
|
var txSizeTests = []txSizeTest{
|
||||||
{
|
{
|
||||||
name: "htlc timeout regular ",
|
name: "htlc timeout regular",
|
||||||
expWeight: input.HtlcTimeoutWeight,
|
expWeight: input.HtlcTimeoutWeight,
|
||||||
genTx: func(t *testing.T) *wire.MsgTx {
|
genTx: func(t *testing.T) *wire.MsgTx {
|
||||||
tx, err := genTimeoutTx(channeldb.SingleFunderBit)
|
return genTimeoutTx(t, channeldb.SingleFunderBit)
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
return tx
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "htlc timeout confirmed",
|
name: "htlc timeout confirmed",
|
||||||
expWeight: input.HtlcTimeoutWeightConfirmed,
|
expWeight: input.HtlcTimeoutWeightConfirmed,
|
||||||
genTx: func(t *testing.T) *wire.MsgTx {
|
genTx: func(t *testing.T) *wire.MsgTx {
|
||||||
tx, err := genTimeoutTx(channeldb.AnchorOutputsBit)
|
return genTimeoutTx(t, channeldb.AnchorOutputsBit)
|
||||||
require.NoError(t, err)
|
},
|
||||||
|
},
|
||||||
return tx
|
{
|
||||||
|
name: "taproot htlc timeout",
|
||||||
|
expWeight: input.TaprootHtlcTimeoutWeight,
|
||||||
|
genTx: func(t *testing.T) *wire.MsgTx {
|
||||||
|
return genTimeoutTx(
|
||||||
|
t, channeldb.SimpleTaprootFeatureBit,
|
||||||
|
)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "htlc success regular",
|
name: "htlc success regular",
|
||||||
// The weight estimate from the spec is off by one, but it's
|
// The weight estimate from the spec is off by one, but it's
|
||||||
// okay since we overestimate the weight.
|
// okay since we overestimate the weight.
|
||||||
expWeight: input.HtlcSuccessWeight - 1,
|
expWeight: input.HtlcSuccessWeight - 1,
|
||||||
genTx: func(t *testing.T) *wire.MsgTx {
|
genTx: func(t *testing.T) *wire.MsgTx {
|
||||||
tx, err := genSuccessTx(channeldb.SingleFunderBit)
|
return genSuccessTx(t, channeldb.SingleFunderBit)
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
return tx
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -966,22 +1534,30 @@ var txSizeTests = []txSizeTest{
|
|||||||
// okay since we overestimate the weight.
|
// okay since we overestimate the weight.
|
||||||
expWeight: input.HtlcSuccessWeightConfirmed - 1,
|
expWeight: input.HtlcSuccessWeightConfirmed - 1,
|
||||||
genTx: func(t *testing.T) *wire.MsgTx {
|
genTx: func(t *testing.T) *wire.MsgTx {
|
||||||
tx, err := genSuccessTx(channeldb.AnchorOutputsBit)
|
return genSuccessTx(t, channeldb.AnchorOutputsBit)
|
||||||
require.NoError(t, err)
|
},
|
||||||
|
},
|
||||||
return tx
|
{
|
||||||
|
name: "taproot htlc success",
|
||||||
|
expWeight: input.TaprootHtlcSuccessWeight,
|
||||||
|
genTx: func(t *testing.T) *wire.MsgTx {
|
||||||
|
return genSuccessTx(
|
||||||
|
t, channeldb.SimpleTaprootFeatureBit,
|
||||||
|
)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestWitnessSizes asserts the correctness of our magic tx size constants.
|
// TestTxSizes asserts the correctness of our magic tx size constants.
|
||||||
func TestTxSizes(t *testing.T) {
|
func TestTxSizes(t *testing.T) {
|
||||||
for _, test := range txSizeTests {
|
for _, test := range txSizeTests {
|
||||||
test := test
|
test := test
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
tx := test.genTx(t)
|
tx := test.genTx(t)
|
||||||
|
|
||||||
weight := blockchain.GetTransactionWeight(btcutil.NewTx(tx))
|
weight := blockchain.GetTransactionWeight(
|
||||||
|
btcutil.NewTx(tx),
|
||||||
|
)
|
||||||
if weight != test.expWeight {
|
if weight != test.expWeight {
|
||||||
t.Fatalf("size mismatch, want: %v, got: %v",
|
t.Fatalf("size mismatch, want: %v, got: %v",
|
||||||
test.expWeight, weight)
|
test.expWeight, weight)
|
||||||
|
|||||||
@@ -224,6 +224,8 @@ func TestTaprootSenderHtlcSpend(t *testing.T) {
|
|||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
|
|
||||||
|
// TODO(roasbeef): use sighash slice
|
||||||
|
|
||||||
witnessGen witnessGen
|
witnessGen witnessGen
|
||||||
|
|
||||||
txInMutator func(txIn *wire.TxIn)
|
txInMutator func(txIn *wire.TxIn)
|
||||||
@@ -437,7 +439,7 @@ type testReceiverHtlcScriptTree struct {
|
|||||||
|
|
||||||
receiverKey *btcec.PrivateKey
|
receiverKey *btcec.PrivateKey
|
||||||
|
|
||||||
revokeKey *btcec.PrivateKey
|
revokeKey btcec.PrivateKey
|
||||||
|
|
||||||
htlcTxOut *wire.TxOut
|
htlcTxOut *wire.TxOut
|
||||||
|
|
||||||
@@ -486,7 +488,7 @@ func newTestReceiverHtlcScriptTree(t *testing.T) *testReceiverHtlcScriptTree {
|
|||||||
preImage: preImage,
|
preImage: preImage,
|
||||||
senderKey: senderKey,
|
senderKey: senderKey,
|
||||||
receiverKey: receiverKey,
|
receiverKey: receiverKey,
|
||||||
revokeKey: revokeKey,
|
revokeKey: *revokeKey,
|
||||||
htlcTxOut: targetTxOut,
|
htlcTxOut: targetTxOut,
|
||||||
htlcAmt: htlcAmt,
|
htlcAmt: htlcAmt,
|
||||||
rootHash: htlcScriptTree.TapscriptRoot,
|
rootHash: htlcScriptTree.TapscriptRoot,
|
||||||
@@ -542,7 +544,7 @@ func htlcReceiverRevocationWitnessGen(sigHash txscript.SigHashType,
|
|||||||
revokeKey := htlcScriptTree.revokeKey
|
revokeKey := htlcScriptTree.revokeKey
|
||||||
signer := &MockSigner{
|
signer := &MockSigner{
|
||||||
Privkeys: []*btcec.PrivateKey{
|
Privkeys: []*btcec.PrivateKey{
|
||||||
revokeKey,
|
&revokeKey,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -637,6 +639,8 @@ func TestTaprootReceiverHtlcSpend(t *testing.T) {
|
|||||||
// signing below.
|
// signing below.
|
||||||
htlcScriptTree := newTestReceiverHtlcScriptTree(t)
|
htlcScriptTree := newTestReceiverHtlcScriptTree(t)
|
||||||
|
|
||||||
|
// TODO(roasbeef): issue with revoke key??? ctrl block even/odd
|
||||||
|
|
||||||
spendTx := wire.NewMsgTx(2)
|
spendTx := wire.NewMsgTx(2)
|
||||||
spendTx.AddTxIn(&wire.TxIn{})
|
spendTx.AddTxIn(&wire.TxIn{})
|
||||||
spendTx.AddTxOut(&wire.TxOut{
|
spendTx.AddTxOut(&wire.TxOut{
|
||||||
|
|||||||
+45
-3
@@ -206,7 +206,7 @@ const (
|
|||||||
// TaprootHtlcAcceptedSuccessSecondLevel is a witness that allows us to
|
// TaprootHtlcAcceptedSuccessSecondLevel is a witness that allows us to
|
||||||
// sweep an HTLC we accepted on our commitment transaction after we go
|
// sweep an HTLC we accepted on our commitment transaction after we go
|
||||||
// to the second level on chain.
|
// to the second level on chain.
|
||||||
TaprootHtlcAcceptedSuceessSecondLevel StandardWitnessType = 26
|
TaprootHtlcAcceptedSuccessSecondLevel StandardWitnessType = 26
|
||||||
|
|
||||||
// TaprootHtlcSecondLevelRevoke is a witness that allows us to sweep an
|
// TaprootHtlcSecondLevelRevoke is a witness that allows us to sweep an
|
||||||
// HTLC on the revoked transaction of the remote party that goes to the
|
// HTLC on the revoked transaction of the remote party that goes to the
|
||||||
@@ -339,8 +339,8 @@ func (wt StandardWitnessType) String() string {
|
|||||||
case TaprootHtlcOfferedTimeoutSecondLevel:
|
case TaprootHtlcOfferedTimeoutSecondLevel:
|
||||||
return "TaprootHtlcOfferedTimeoutSecondLevel"
|
return "TaprootHtlcOfferedTimeoutSecondLevel"
|
||||||
|
|
||||||
case TaprootHtlcAcceptedSuceessSecondLevel:
|
case TaprootHtlcAcceptedSuccessSecondLevel:
|
||||||
return "TaprootHtlcAcceptedSuceessSecondLevel"
|
return "TaprootHtlcAcceptedSuccessSecondLevel"
|
||||||
|
|
||||||
case TaprootHtlcSecondLevelRevoke:
|
case TaprootHtlcSecondLevelRevoke:
|
||||||
return "TaprootHtlcSecondLevelRevoke"
|
return "TaprootHtlcSecondLevelRevoke"
|
||||||
@@ -621,6 +621,48 @@ func (wt StandardWitnessType) SizeUpperBound() (int, bool, error) {
|
|||||||
|
|
||||||
case TaprootPubKeySpend:
|
case TaprootPubKeySpend:
|
||||||
return TaprootKeyPathCustomSighashWitnessSize, false, nil
|
return TaprootKeyPathCustomSighashWitnessSize, false, nil
|
||||||
|
|
||||||
|
// Sweeping a self output after a delay for taproot channels.
|
||||||
|
case TaprootLocalCommitSpend:
|
||||||
|
return TaprootToLocalWitnessSize, false, nil
|
||||||
|
|
||||||
|
// Sweeping a self output after the remote party fro ce closes. Must
|
||||||
|
// wait 1 CSV.
|
||||||
|
case TaprootRemoteCommitSpend:
|
||||||
|
return TaprootToRemoteWitnessSize, false, nil
|
||||||
|
|
||||||
|
// Sweeping our anchor output with a key spend witness.
|
||||||
|
case TaprootAnchorSweepSpend:
|
||||||
|
return TaprootAnchorWitnessSize, false, nil
|
||||||
|
|
||||||
|
case TaprootHtlcOfferedTimeoutSecondLevel,
|
||||||
|
TaprootHtlcAcceptedSuccessSecondLevel:
|
||||||
|
|
||||||
|
return TaprootSecondLevelHtlcWitnessSize, false, nil
|
||||||
|
|
||||||
|
case TaprootHtlcSecondLevelRevoke:
|
||||||
|
return TaprootSecondLevelRevokeWitnessSize, false, nil
|
||||||
|
|
||||||
|
case TaprootHtlcAcceptedRevoke:
|
||||||
|
return TaprootAcceptedRevokeWitnessSize, false, nil
|
||||||
|
|
||||||
|
case TaprootHtlcOfferedRevoke:
|
||||||
|
return TaprootOfferedRevokeWitnessSize, false, nil
|
||||||
|
|
||||||
|
case TaprootHtlcOfferedRemoteTimeout:
|
||||||
|
return TaprootHtlcOfferedRemoteTimeoutWitnessSize, false, nil
|
||||||
|
|
||||||
|
case TaprootHtlcLocalOfferedTimeout:
|
||||||
|
return TaprootOfferedLocalTimeoutWitnessSize, false, nil
|
||||||
|
|
||||||
|
case TaprootHtlcAcceptedRemoteSuccess:
|
||||||
|
return TaprootHtlcAcceptedRemoteSuccessWitnessSize, false, nil
|
||||||
|
|
||||||
|
case TaprootHtlcAcceptedLocalSuccess:
|
||||||
|
return TaprootHtlcAcceptedLocalSuccessWitnessSize, false, nil
|
||||||
|
|
||||||
|
case TaprootCommitmentRevoke:
|
||||||
|
return TaprootToLocalRevokeWitnessSize, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0, false, fmt.Errorf("unexpected witness type: %v", wt)
|
return 0, false, fmt.Errorf("unexpected witness type: %v", wt)
|
||||||
|
|||||||
@@ -242,7 +242,9 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount,
|
|||||||
// Based on the channel type, we determine the initial commit weight
|
// Based on the channel type, we determine the initial commit weight
|
||||||
// and fee.
|
// and fee.
|
||||||
commitWeight := int64(input.CommitWeight)
|
commitWeight := int64(input.CommitWeight)
|
||||||
if req.CommitType.HasAnchors() {
|
if req.CommitType.IsTaproot() {
|
||||||
|
commitWeight = input.TaprootCommitWeight
|
||||||
|
} else if req.CommitType.HasAnchors() {
|
||||||
commitWeight = int64(input.AnchorCommitWeight)
|
commitWeight = int64(input.AnchorCommitWeight)
|
||||||
}
|
}
|
||||||
commitFee := req.CommitFeePerKw.FeeForWeight(commitWeight)
|
commitFee := req.CommitFeePerKw.FeeForWeight(commitWeight)
|
||||||
|
|||||||
Reference in new issue
Block a user