2019-01-16 15:47:43 +01:00
|
|
|
package input
|
2017-05-07 13:04:28 +02:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
2018-06-05 03:34:16 +02:00
|
|
|
"github.com/btcsuite/btcd/txscript"
|
|
|
|
"github.com/btcsuite/btcd/wire"
|
2017-05-07 13:04:28 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
// WitnessType determines how an output's witness will be generated. The
|
|
|
|
// default commitmentTimeLock type will generate a witness that will allow
|
|
|
|
// spending of a time-locked transaction enforced by CheckSequenceVerify.
|
|
|
|
type WitnessType uint16
|
|
|
|
|
|
|
|
const (
|
2017-10-02 05:54:23 +02:00
|
|
|
// CommitmentTimeLock is a witness that allows us to spend the output of
|
|
|
|
// a commitment transaction after a relative lock-time lockout.
|
2017-05-07 13:04:28 +02:00
|
|
|
CommitmentTimeLock WitnessType = 0
|
|
|
|
|
2017-10-02 05:54:23 +02:00
|
|
|
// CommitmentNoDelay is a witness that allows us to spend a settled
|
|
|
|
// no-delay output immediately on a counterparty's commitment
|
|
|
|
// transaction.
|
2017-05-07 13:04:28 +02:00
|
|
|
CommitmentNoDelay WitnessType = 1
|
|
|
|
|
2017-10-02 05:54:23 +02:00
|
|
|
// CommitmentRevoke is a witness that allows us to sweep the settled
|
|
|
|
// output of a malicious counterparty's who broadcasts a revoked
|
|
|
|
// commitment transaction.
|
2017-05-07 13:04:28 +02:00
|
|
|
CommitmentRevoke WitnessType = 2
|
2017-09-06 22:39:45 +02:00
|
|
|
|
2018-01-17 02:59:43 +01:00
|
|
|
// HtlcOfferedRevoke is a witness that allows us to sweep an HTLC which
|
|
|
|
// we offered to the remote party in the case that they broadcast a
|
2018-02-07 04:11:11 +01:00
|
|
|
// revoked commitment state.
|
2017-09-06 22:39:45 +02:00
|
|
|
HtlcOfferedRevoke WitnessType = 3
|
|
|
|
|
|
|
|
// HtlcAcceptedRevoke is a witness that allows us to sweep an HTLC
|
2018-01-17 02:59:43 +01:00
|
|
|
// output sent to us in the case that the remote party broadcasts a
|
|
|
|
// revoked commitment state.
|
2017-09-06 22:39:45 +02:00
|
|
|
HtlcAcceptedRevoke WitnessType = 4
|
2017-10-02 05:54:23 +02:00
|
|
|
|
2018-01-17 02:59:43 +01:00
|
|
|
// HtlcOfferedTimeoutSecondLevel is a witness that allows us to sweep
|
|
|
|
// an HTLC output that we extended to a party, but was never fulfilled.
|
|
|
|
// This HTLC output isn't directly on the commitment transaction, but
|
|
|
|
// is the result of a confirmed second-level HTLC transaction. As a
|
|
|
|
// result, we can only spend this after a CSV delay.
|
|
|
|
HtlcOfferedTimeoutSecondLevel WitnessType = 5
|
|
|
|
|
|
|
|
// HtlcAcceptedSuccessSecondLevel is a witness that allows us to sweep
|
|
|
|
// an HTLC output that was offered to us, and for which we have a
|
2018-02-07 04:11:11 +01:00
|
|
|
// payment preimage. This HTLC output isn't directly on our commitment
|
2018-01-17 02:59:43 +01:00
|
|
|
// transaction, but is the result of confirmed second-level HTLC
|
|
|
|
// transaction. As a result, we can only spend this after a CSV delay.
|
|
|
|
HtlcAcceptedSuccessSecondLevel WitnessType = 6
|
|
|
|
|
|
|
|
// HtlcOfferedRemoteTimeout is a witness that allows us to sweep an
|
|
|
|
// HTLC that we offered to the remote party which lies in the
|
|
|
|
// commitment transaction of the remote party. We can spend this output
|
|
|
|
// after the absolute CLTV timeout of the HTLC as passed.
|
|
|
|
HtlcOfferedRemoteTimeout WitnessType = 7
|
|
|
|
|
|
|
|
// HtlcAcceptedRemoteSuccess is a witness that allows us to sweep an
|
|
|
|
// HTLC that was offered to us by the remote party. We use this witness
|
|
|
|
// in the case that the remote party goes to chain, and we know the
|
|
|
|
// pre-image to the HTLC. We can sweep this without any additional
|
|
|
|
// timeout.
|
|
|
|
HtlcAcceptedRemoteSuccess WitnessType = 8
|
2018-01-21 04:57:34 +01:00
|
|
|
|
|
|
|
// HtlcSecondLevelRevoke is a witness that allows us to sweep an HTLC
|
|
|
|
// from the remote party's commitment transaction in the case that the
|
|
|
|
// broadcast a revoked commitment, but then also immediately attempt to
|
|
|
|
// go to the second level to claim the HTLC.
|
|
|
|
HtlcSecondLevelRevoke WitnessType = 9
|
2018-11-18 05:51:58 +01:00
|
|
|
|
|
|
|
// WitnessKeyHash is a witness type that allows us to spend a regular
|
|
|
|
// p2wkh output that's sent to an output which is under complete
|
|
|
|
// control of the backing wallet.
|
|
|
|
WitnessKeyHash WitnessType = 10
|
|
|
|
|
|
|
|
// NestedWitnessKeyHash is a witness type that allows us to sweep an
|
|
|
|
// output that sends to a nested P2SH script that pays to a key solely
|
|
|
|
// under our control. The witness generated needs to include the
|
|
|
|
NestedWitnessKeyHash WitnessType = 11
|
2017-05-07 13:04:28 +02:00
|
|
|
)
|
|
|
|
|
2018-12-17 01:52:57 +01:00
|
|
|
// Stirng returns a human readable version of the target WitnessType.
|
|
|
|
func (wt WitnessType) String() string {
|
|
|
|
switch wt {
|
|
|
|
case CommitmentTimeLock:
|
|
|
|
return "CommitmentTimeLock"
|
|
|
|
|
|
|
|
case CommitmentNoDelay:
|
|
|
|
return "CommitmentNoDelay"
|
|
|
|
|
|
|
|
case CommitmentRevoke:
|
|
|
|
return "CommitmentRevoke"
|
|
|
|
|
|
|
|
case HtlcOfferedRevoke:
|
|
|
|
return "HtlcOfferedRevoke"
|
|
|
|
|
|
|
|
case HtlcAcceptedRevoke:
|
|
|
|
return "HtlcAcceptedRevoke"
|
|
|
|
|
|
|
|
case HtlcOfferedTimeoutSecondLevel:
|
|
|
|
return "HtlcOfferedTimeoutSecondLevel"
|
|
|
|
|
|
|
|
case HtlcAcceptedSuccessSecondLevel:
|
|
|
|
return "HtlcAcceptedSuccessSecondLevel"
|
|
|
|
|
|
|
|
case HtlcOfferedRemoteTimeout:
|
|
|
|
return "HtlcOfferedRemoteTimeout"
|
|
|
|
|
|
|
|
case HtlcAcceptedRemoteSuccess:
|
|
|
|
return "HtlcAcceptedRemoteSuccess"
|
|
|
|
|
|
|
|
case HtlcSecondLevelRevoke:
|
|
|
|
return "HtlcSecondLevelRevoke"
|
|
|
|
|
|
|
|
default:
|
|
|
|
return fmt.Sprintf("Unknown WitnessType: %v", uint32(wt))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-07 13:04:28 +02:00
|
|
|
// WitnessGenerator represents a function which is able to generate the final
|
2018-11-18 05:48:41 +01:00
|
|
|
// witness for a particular public key script. Additionally, if required, this
|
|
|
|
// function will also return the sigScript for spending nested P2SH witness
|
|
|
|
// outputs. This function acts as an abstraction layer, hiding the details of
|
|
|
|
// the underlying script.
|
2017-05-07 13:04:28 +02:00
|
|
|
type WitnessGenerator func(tx *wire.MsgTx, hc *txscript.TxSigHashes,
|
2019-01-16 15:47:43 +01:00
|
|
|
inputIndex int) (*Script, error)
|
2017-05-07 13:04:28 +02:00
|
|
|
|
2018-11-18 05:48:41 +01:00
|
|
|
// GenWitnessFunc will return a WitnessGenerator function that an output uses
|
|
|
|
// to generate the witness and optionally the sigScript for a sweep
|
|
|
|
// transaction. The sigScript will be generated if the witness type warrants
|
|
|
|
// one for spending, such as the NestedWitnessKeyHash witness type.
|
2017-08-22 02:03:16 +02:00
|
|
|
func (wt WitnessType) GenWitnessFunc(signer Signer,
|
2017-05-07 13:04:28 +02:00
|
|
|
descriptor *SignDescriptor) WitnessGenerator {
|
|
|
|
|
|
|
|
return func(tx *wire.MsgTx, hc *txscript.TxSigHashes,
|
2019-01-16 15:47:43 +01:00
|
|
|
inputIndex int) (*Script, error) {
|
2017-05-07 13:04:28 +02:00
|
|
|
|
|
|
|
desc := descriptor
|
|
|
|
desc.SigHashes = hc
|
|
|
|
desc.InputIndex = inputIndex
|
|
|
|
|
|
|
|
switch wt {
|
|
|
|
case CommitmentTimeLock:
|
2018-11-18 05:48:41 +01:00
|
|
|
witness, err := CommitSpendTimeout(signer, desc, tx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-01-16 15:47:43 +01:00
|
|
|
return &Script{
|
2018-11-18 05:48:41 +01:00
|
|
|
Witness: witness,
|
|
|
|
}, nil
|
2018-01-17 02:59:43 +01:00
|
|
|
|
2017-05-07 13:04:28 +02:00
|
|
|
case CommitmentNoDelay:
|
2018-11-18 05:48:41 +01:00
|
|
|
witness, err := CommitSpendNoDelay(signer, desc, tx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-01-16 15:47:43 +01:00
|
|
|
return &Script{
|
2018-11-18 05:48:41 +01:00
|
|
|
Witness: witness,
|
|
|
|
}, nil
|
2018-01-17 02:59:43 +01:00
|
|
|
|
2017-05-07 13:04:28 +02:00
|
|
|
case CommitmentRevoke:
|
2018-11-18 05:48:41 +01:00
|
|
|
witness, err := CommitSpendRevoke(signer, desc, tx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-01-16 15:47:43 +01:00
|
|
|
return &Script{
|
2018-11-18 05:48:41 +01:00
|
|
|
Witness: witness,
|
|
|
|
}, nil
|
2018-01-17 02:59:43 +01:00
|
|
|
|
2017-09-06 22:39:45 +02:00
|
|
|
case HtlcOfferedRevoke:
|
2018-11-18 05:48:41 +01:00
|
|
|
witness, err := ReceiverHtlcSpendRevoke(signer, desc, tx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-01-16 15:47:43 +01:00
|
|
|
return &Script{
|
2018-11-18 05:48:41 +01:00
|
|
|
Witness: witness,
|
|
|
|
}, nil
|
2018-01-17 02:59:43 +01:00
|
|
|
|
2017-09-06 22:39:45 +02:00
|
|
|
case HtlcAcceptedRevoke:
|
2018-11-18 05:48:41 +01:00
|
|
|
witness, err := SenderHtlcSpendRevoke(signer, desc, tx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-01-16 15:47:43 +01:00
|
|
|
return &Script{
|
2018-11-18 05:48:41 +01:00
|
|
|
Witness: witness,
|
|
|
|
}, nil
|
2018-01-17 02:59:43 +01:00
|
|
|
|
|
|
|
case HtlcOfferedTimeoutSecondLevel:
|
2018-11-18 05:48:41 +01:00
|
|
|
witness, err := HtlcSecondLevelSpend(signer, desc, tx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-01-16 15:47:43 +01:00
|
|
|
return &Script{
|
2018-11-18 05:48:41 +01:00
|
|
|
Witness: witness,
|
|
|
|
}, nil
|
2018-01-17 02:59:43 +01:00
|
|
|
|
|
|
|
case HtlcAcceptedSuccessSecondLevel:
|
2018-11-18 05:48:41 +01:00
|
|
|
witness, err := HtlcSecondLevelSpend(signer, desc, tx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-01-16 15:47:43 +01:00
|
|
|
return &Script{
|
2018-11-18 05:48:41 +01:00
|
|
|
Witness: witness,
|
|
|
|
}, nil
|
2018-01-17 02:59:43 +01:00
|
|
|
|
|
|
|
case HtlcOfferedRemoteTimeout:
|
|
|
|
// We pass in a value of -1 for the timeout, as we
|
|
|
|
// expect the caller to have already set the lock time
|
|
|
|
// value.
|
2019-01-16 15:47:43 +01:00
|
|
|
witness, err := ReceiverHtlcSpendTimeout(signer, desc, tx, -1)
|
2018-11-18 05:48:41 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-01-16 15:47:43 +01:00
|
|
|
return &Script{
|
2018-11-18 05:48:41 +01:00
|
|
|
Witness: witness,
|
|
|
|
}, nil
|
2018-01-17 02:59:43 +01:00
|
|
|
|
2018-01-21 04:57:34 +01:00
|
|
|
case HtlcSecondLevelRevoke:
|
2019-01-16 15:47:43 +01:00
|
|
|
witness, err := HtlcSpendRevoke(signer, desc, tx)
|
2018-11-18 05:48:41 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2019-01-16 15:47:43 +01:00
|
|
|
return &Script{
|
2018-11-18 05:48:41 +01:00
|
|
|
Witness: witness,
|
|
|
|
}, nil
|
|
|
|
|
2018-11-18 05:51:58 +01:00
|
|
|
case WitnessKeyHash:
|
|
|
|
fallthrough
|
|
|
|
case NestedWitnessKeyHash:
|
|
|
|
return signer.ComputeInputScript(tx, desc)
|
2018-01-21 04:57:34 +01:00
|
|
|
|
2017-05-07 13:04:28 +02:00
|
|
|
default:
|
|
|
|
return nil, fmt.Errorf("unknown witness type: %v", wt)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|