psbt: add new MuSig2 fields to inputs and outputs

This commit is contained in:
Oliver Gugger 2024-06-14 11:06:45 +02:00
parent b949c67c06
commit bf1e09679f
No known key found for this signature in database
GPG key ID: 8E4256593F177720
3 changed files with 141 additions and 0 deletions

View file

@ -28,6 +28,9 @@ type PInput struct {
TaprootBip32Derivation []*TaprootBip32Derivation
TaprootInternalKey []byte
TaprootMerkleRoot []byte
MuSig2Participants []*MuSig2Participants
MuSig2PubNonces []*MuSig2PubNonce
MuSig2PartialSigs []*MuSig2PartialSig
Unknowns []*Unknown
}
@ -363,6 +366,60 @@ func (pi *PInput) deserialize(r io.Reader) error {
pi.TaprootMerkleRoot = value
case MuSig2ParticipantsInputType:
participants, err := ReadMuSig2Participants(
keyData, value,
)
if err != nil {
return err
}
// Duplicate keys are not allowed.
newKey := participants.KeyData()
for _, x := range pi.MuSig2Participants {
if bytes.Equal(x.KeyData(), newKey) {
return ErrDuplicateKey
}
}
pi.MuSig2Participants = append(
pi.MuSig2Participants, participants,
)
case MuSig2PubNoncesInputType:
nonce, err := ReadMuSig2PubNonce(keyData, value)
if err != nil {
return err
}
// Duplicate keys are not allowed.
newKey := nonce.KeyData()
for _, x := range pi.MuSig2PubNonces {
if bytes.Equal(x.KeyData(), newKey) {
return ErrDuplicateKey
}
}
pi.MuSig2PubNonces = append(pi.MuSig2PubNonces, nonce)
case MuSig2PartialSigsInputType:
partialSig, err := ReadMuSig2PartialSig(keyData, value)
if err != nil {
return err
}
// Duplicate keys are not allowed.
newKey := partialSig.KeyData()
for _, x := range pi.MuSig2PartialSigs {
if bytes.Equal(x.KeyData(), newKey) {
return ErrDuplicateKey
}
}
pi.MuSig2PartialSigs = append(
pi.MuSig2PartialSigs, partialSig,
)
default:
// A fall through case for any proprietary types.
keyCodeAndData := append(
@ -572,6 +629,36 @@ func (pi *PInput) serialize(w io.Writer) error {
return err
}
}
for _, participants := range pi.MuSig2Participants {
err := SerializeMuSig2Participants(
w, uint8(MuSig2ParticipantsInputType),
participants,
)
if err != nil {
return err
}
}
for _, nonce := range pi.MuSig2PubNonces {
err := SerializeMuSig2PubNonce(
w, uint8(MuSig2PubNoncesInputType),
nonce,
)
if err != nil {
return err
}
}
for _, sig := range pi.MuSig2PartialSigs {
err := SerializeMuSig2PartialSig(
w, uint8(MuSig2PartialSigsInputType),
sig,
)
if err != nil {
return err
}
}
}
if pi.FinalScriptSig != nil {

View file

@ -17,6 +17,7 @@ type POutput struct {
TaprootInternalKey []byte
TaprootTapTree []byte
TaprootBip32Derivation []*TaprootBip32Derivation
MuSig2Participants []*MuSig2Participants
Unknowns []*Unknown
}
@ -144,6 +145,26 @@ func (po *POutput) deserialize(r io.Reader) error {
po.TaprootBip32Derivation, taprootDerivation,
)
case MuSig2ParticipantsOutputType:
participants, err := ReadMuSig2Participants(
keyData, value,
)
if err != nil {
return err
}
// Duplicate keys are not allowed.
newKey := participants.AggregateKey
for _, x := range po.MuSig2Participants {
if x.AggregateKey.IsEqual(newKey) {
return ErrDuplicateKey
}
}
po.MuSig2Participants = append(
po.MuSig2Participants, participants,
)
default:
// A fall through case for any proprietary types.
keyCodeAndData := append(
@ -246,6 +267,15 @@ func (po *POutput) serialize(w io.Writer) error {
}
}
for _, participants := range po.MuSig2Participants {
err := SerializeMuSig2Participants(
w, uint8(MuSig2ParticipantsOutputType), participants,
)
if err != nil {
return err
}
}
// Unknown is a special case; we don't have a key type, only a key and
// a value field
for _, kv := range po.Unknowns {

View file

@ -151,6 +151,24 @@ const (
// 32-byte hash denoting the root hash of a merkle tree of scripts.
TaprootMerkleRootType InputType = 0x18
// MuSig2ParticipantsInputType is a type that carries the participant
// public keys and aggregated key for a MuSig2 signing session
// ({0x1a}|{aggregate_key}). The value is a list of 33-byte compressed
// public keys in the order required for aggregation.
MuSig2ParticipantsInputType InputType = 0x1a
// MuSig2PubNoncesInputType is a type that carries the public nonces
// provided by participants in a MuSig2 signing session
// ({0x1b}|{participant_key}|{aggregate_key}[|{tapleaf_hash}]). The
// value is the 66-byte public nonces provided by the participant.
MuSig2PubNoncesInputType InputType = 0x1b
// MuSig2PartialSigsInputType is a type that carries the partial
// signatures provided by participants in a MuSig2 signing session
// ({0x1c}|{participant_key}|{aggregate_key}[|{tapleaf_hash}]). The
// value is the 32-byte partial signature provided by the participant.
MuSig2PartialSigsInputType InputType = 0x1c
// ProprietaryInputType is a custom type for use by devs.
//
// The key ({0xFC}|<prefix>|{subtype}|{key data}), is a Variable length
@ -200,4 +218,10 @@ const (
// followed by said number of 32-byte leaf hashes. The rest of the value
// is then identical to the Bip32DerivationInputType value.
TaprootBip32DerivationOutputType OutputType = 7
// MuSig2ParticipantsOutputType is a type that carries the participant
// public keys and aggregated key for a MuSig2 signing session
// ({0x08}|{aggregate_key}). The value is a list of 33-byte compressed
// public keys in the order required for aggregation.
MuSig2ParticipantsOutputType OutputType = 0x08
)