contractcourt: convert taprootBriefcase to use new tlv record type

This commit doesn't yet go all the way to modify all the other records
quite yet.
This commit is contained in:
Olaoluwa Osuntokun 2024-06-03 22:55:50 -07:00
parent ed02d20c04
commit 79f080da36
4 changed files with 86 additions and 96 deletions

View file

@ -1629,13 +1629,13 @@ func taprootBriefcaseFromRetInfo(retInfo *retributionInfo) *taprootBriefcase {
// commitment, we'll need to stash the control block.
case input.TaprootRemoteCommitSpend:
//nolint:lll
tapCase.CtrlBlocks.CommitSweepCtrlBlock = bo.signDesc.ControlBlock
tapCase.CtrlBlocks.Val.CommitSweepCtrlBlock = bo.signDesc.ControlBlock
// To spend the revoked output again, we'll store the same
// control block value as above, but in a different place.
case input.TaprootCommitmentRevoke:
//nolint:lll
tapCase.CtrlBlocks.RevokeSweepCtrlBlock = bo.signDesc.ControlBlock
tapCase.CtrlBlocks.Val.RevokeSweepCtrlBlock = bo.signDesc.ControlBlock
// For spending the HTLC outputs, we'll store the first and
// second level tweak values.
@ -1649,10 +1649,10 @@ func taprootBriefcaseFromRetInfo(retInfo *retributionInfo) *taprootBriefcase {
secondLevelTweak := bo.secondLevelTapTweak
//nolint:lll
tapCase.TapTweaks.BreachedHtlcTweaks[resID] = firstLevelTweak
tapCase.TapTweaks.Val.BreachedHtlcTweaks[resID] = firstLevelTweak
//nolint:lll
tapCase.TapTweaks.BreachedSecondLevelHltcTweaks[resID] = secondLevelTweak
tapCase.TapTweaks.Val.BreachedSecondLevelHltcTweaks[resID] = secondLevelTweak
}
}
@ -1672,13 +1672,13 @@ func applyTaprootRetInfo(tapCase *taprootBriefcase,
// commitment, we'll apply the control block.
case input.TaprootRemoteCommitSpend:
//nolint:lll
bo.signDesc.ControlBlock = tapCase.CtrlBlocks.CommitSweepCtrlBlock
bo.signDesc.ControlBlock = tapCase.CtrlBlocks.Val.CommitSweepCtrlBlock
// To spend the revoked output again, we'll apply the same
// control block value as above, but to a different place.
case input.TaprootCommitmentRevoke:
//nolint:lll
bo.signDesc.ControlBlock = tapCase.CtrlBlocks.RevokeSweepCtrlBlock
bo.signDesc.ControlBlock = tapCase.CtrlBlocks.Val.RevokeSweepCtrlBlock
// For spending the HTLC outputs, we'll apply the first and
// second level tweak values.
@ -1687,7 +1687,8 @@ func applyTaprootRetInfo(tapCase *taprootBriefcase,
case input.TaprootHtlcOfferedRevoke:
resID := newResolverID(bo.OutPoint())
tap1, ok := tapCase.TapTweaks.BreachedHtlcTweaks[resID]
//nolint:lll
tap1, ok := tapCase.TapTweaks.Val.BreachedHtlcTweaks[resID]
if !ok {
return fmt.Errorf("unable to find taproot "+
"tweak for: %v", bo.OutPoint())
@ -1695,7 +1696,7 @@ func applyTaprootRetInfo(tapCase *taprootBriefcase,
bo.signDesc.TapTweak = tap1[:]
//nolint:lll
tap2, ok := tapCase.TapTweaks.BreachedSecondLevelHltcTweaks[resID]
tap2, ok := tapCase.TapTweaks.Val.BreachedSecondLevelHltcTweaks[resID]
if !ok {
return fmt.Errorf("unable to find taproot "+
"tweak for: %v", bo.OutPoint())

View file

@ -1553,7 +1553,7 @@ func encodeTaprootAuxData(w io.Writer, c *ContractResolutions) error {
commitResolution := c.CommitResolution
commitSignDesc := commitResolution.SelfOutputSignDesc
//nolint:lll
tapCase.CtrlBlocks.CommitSweepCtrlBlock = commitSignDesc.ControlBlock
tapCase.CtrlBlocks.Val.CommitSweepCtrlBlock = commitSignDesc.ControlBlock
}
for _, htlc := range c.HtlcResolutions.IncomingHTLCs {
@ -1571,7 +1571,7 @@ func encodeTaprootAuxData(w io.Writer, c *ContractResolutions) error {
htlc.SignedSuccessTx.TxIn[0].PreviousOutPoint,
)
//nolint:lll
tapCase.CtrlBlocks.SecondLevelCtrlBlocks[resID] = ctrlBlock
tapCase.CtrlBlocks.Val.SecondLevelCtrlBlocks[resID] = ctrlBlock
// For HTLCs we need to go to the second level for, we
// also need to store the control block needed to
@ -1580,12 +1580,12 @@ func encodeTaprootAuxData(w io.Writer, c *ContractResolutions) error {
//nolint:lll
bridgeCtrlBlock := htlc.SignDetails.SignDesc.ControlBlock
//nolint:lll
tapCase.CtrlBlocks.IncomingHtlcCtrlBlocks[resID] = bridgeCtrlBlock
tapCase.CtrlBlocks.Val.IncomingHtlcCtrlBlocks[resID] = bridgeCtrlBlock
}
} else {
resID := newResolverID(htlc.ClaimOutpoint)
//nolint:lll
tapCase.CtrlBlocks.IncomingHtlcCtrlBlocks[resID] = ctrlBlock
tapCase.CtrlBlocks.Val.IncomingHtlcCtrlBlocks[resID] = ctrlBlock
}
}
for _, htlc := range c.HtlcResolutions.OutgoingHTLCs {
@ -1603,7 +1603,7 @@ func encodeTaprootAuxData(w io.Writer, c *ContractResolutions) error {
htlc.SignedTimeoutTx.TxIn[0].PreviousOutPoint,
)
//nolint:lll
tapCase.CtrlBlocks.SecondLevelCtrlBlocks[resID] = ctrlBlock
tapCase.CtrlBlocks.Val.SecondLevelCtrlBlocks[resID] = ctrlBlock
// For HTLCs we need to go to the second level for, we
// also need to store the control block needed to
@ -1614,18 +1614,18 @@ func encodeTaprootAuxData(w io.Writer, c *ContractResolutions) error {
//nolint:lll
bridgeCtrlBlock := htlc.SignDetails.SignDesc.ControlBlock
//nolint:lll
tapCase.CtrlBlocks.OutgoingHtlcCtrlBlocks[resID] = bridgeCtrlBlock
tapCase.CtrlBlocks.Val.OutgoingHtlcCtrlBlocks[resID] = bridgeCtrlBlock
}
} else {
resID := newResolverID(htlc.ClaimOutpoint)
//nolint:lll
tapCase.CtrlBlocks.OutgoingHtlcCtrlBlocks[resID] = ctrlBlock
tapCase.CtrlBlocks.Val.OutgoingHtlcCtrlBlocks[resID] = ctrlBlock
}
}
if c.AnchorResolution != nil {
anchorSignDesc := c.AnchorResolution.AnchorSignDescriptor
tapCase.TapTweaks.AnchorTweak = anchorSignDesc.TapTweak
tapCase.TapTweaks.Val.AnchorTweak = anchorSignDesc.TapTweak
}
return tapCase.Encode(w)
@ -1639,7 +1639,7 @@ func decodeTapRootAuxData(r io.Reader, c *ContractResolutions) error {
if c.CommitResolution != nil {
c.CommitResolution.SelfOutputSignDesc.ControlBlock =
tapCase.CtrlBlocks.CommitSweepCtrlBlock
tapCase.CtrlBlocks.Val.CommitSweepCtrlBlock
}
for i := range c.HtlcResolutions.IncomingHTLCs {
@ -1652,19 +1652,19 @@ func decodeTapRootAuxData(r io.Reader, c *ContractResolutions) error {
)
//nolint:lll
ctrlBlock := tapCase.CtrlBlocks.SecondLevelCtrlBlocks[resID]
ctrlBlock := tapCase.CtrlBlocks.Val.SecondLevelCtrlBlocks[resID]
htlc.SweepSignDesc.ControlBlock = ctrlBlock
//nolint:lll
if htlc.SignDetails != nil {
bridgeCtrlBlock := tapCase.CtrlBlocks.IncomingHtlcCtrlBlocks[resID]
bridgeCtrlBlock := tapCase.CtrlBlocks.Val.IncomingHtlcCtrlBlocks[resID]
htlc.SignDetails.SignDesc.ControlBlock = bridgeCtrlBlock
}
} else {
resID = newResolverID(htlc.ClaimOutpoint)
//nolint:lll
ctrlBlock := tapCase.CtrlBlocks.IncomingHtlcCtrlBlocks[resID]
ctrlBlock := tapCase.CtrlBlocks.Val.IncomingHtlcCtrlBlocks[resID]
htlc.SweepSignDesc.ControlBlock = ctrlBlock
}
@ -1680,19 +1680,19 @@ func decodeTapRootAuxData(r io.Reader, c *ContractResolutions) error {
)
//nolint:lll
ctrlBlock := tapCase.CtrlBlocks.SecondLevelCtrlBlocks[resID]
ctrlBlock := tapCase.CtrlBlocks.Val.SecondLevelCtrlBlocks[resID]
htlc.SweepSignDesc.ControlBlock = ctrlBlock
//nolint:lll
if htlc.SignDetails != nil {
bridgeCtrlBlock := tapCase.CtrlBlocks.OutgoingHtlcCtrlBlocks[resID]
bridgeCtrlBlock := tapCase.CtrlBlocks.Val.OutgoingHtlcCtrlBlocks[resID]
htlc.SignDetails.SignDesc.ControlBlock = bridgeCtrlBlock
}
} else {
resID = newResolverID(htlc.ClaimOutpoint)
//nolint:lll
ctrlBlock := tapCase.CtrlBlocks.OutgoingHtlcCtrlBlocks[resID]
ctrlBlock := tapCase.CtrlBlocks.Val.OutgoingHtlcCtrlBlocks[resID]
htlc.SweepSignDesc.ControlBlock = ctrlBlock
}
@ -1701,7 +1701,7 @@ func decodeTapRootAuxData(r io.Reader, c *ContractResolutions) error {
if c.AnchorResolution != nil {
c.AnchorResolution.AnchorSignDescriptor.TapTweak =
tapCase.TapTweaks.AnchorTweak
tapCase.TapTweaks.Val.AnchorTweak
}
return nil

View file

@ -8,9 +8,6 @@ import (
)
const (
taprootCtrlBlockType tlv.Type = 0
taprootTapTweakType tlv.Type = 1
commitCtrlBlockType tlv.Type = 0
revokeCtrlBlockType tlv.Type = 1
outgoingHtlcCtrlBlockType tlv.Type = 2
@ -26,36 +23,37 @@ const (
// information we need to sweep taproot outputs.
type taprootBriefcase struct {
// CtrlBlock is the set of control block for the taproot outputs.
CtrlBlocks *ctrlBlocks
CtrlBlocks tlv.RecordT[tlv.TlvType0, ctrlBlocks]
// TapTweaks is the set of taproot tweaks for the taproot outputs that
// are to be spent via a keyspend path. This includes anchors, and any
// revocation paths.
TapTweaks *tapTweaks
TapTweaks tlv.RecordT[tlv.TlvType1, tapTweaks]
}
// TODO(roasbeef): morph into new tlv record
// newTaprootBriefcase returns a new instance of the taproot specific briefcase
// variant.
func newTaprootBriefcase() *taprootBriefcase {
return &taprootBriefcase{
CtrlBlocks: newCtrlBlocks(),
TapTweaks: newTapTweaks(),
CtrlBlocks: tlv.NewRecordT[tlv.TlvType0](newCtrlBlocks()),
TapTweaks: tlv.NewRecordT[tlv.TlvType1](newTapTweaks()),
}
}
// EncodeRecords returns a slice of TLV records that should be encoded.
func (t *taprootBriefcase) EncodeRecords() []tlv.Record {
return []tlv.Record{
newCtrlBlocksRecord(&t.CtrlBlocks),
newTapTweaksRecord(&t.TapTweaks),
records := []tlv.Record{
t.CtrlBlocks.Record(), t.TapTweaks.Record(),
}
return records
}
// DecodeRecords returns a slice of TLV records that should be decoded.
func (t *taprootBriefcase) DecodeRecords() []tlv.Record {
return []tlv.Record{
newCtrlBlocksRecord(&t.CtrlBlocks),
newTapTweaksRecord(&t.TapTweaks),
t.CtrlBlocks.Record(), t.TapTweaks.Record(),
}
}
@ -76,7 +74,12 @@ func (t *taprootBriefcase) Decode(r io.Reader) error {
return err
}
return stream.Decode(r)
_, err = stream.DecodeWithParsedTypes(r)
if err != nil {
return err
}
return nil
}
// resolverCtrlBlocks is a map of resolver IDs to their corresponding control
@ -216,8 +219,8 @@ type ctrlBlocks struct {
}
// newCtrlBlocks returns a new instance of the ctrlBlocks struct.
func newCtrlBlocks() *ctrlBlocks {
return &ctrlBlocks{
func newCtrlBlocks() ctrlBlocks {
return ctrlBlocks{
OutgoingHtlcCtrlBlocks: newResolverCtrlBlocks(),
IncomingHtlcCtrlBlocks: newResolverCtrlBlocks(),
SecondLevelCtrlBlocks: newResolverCtrlBlocks(),
@ -260,7 +263,7 @@ func varBytesDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error {
// ctrlBlockEncoder is a custom TLV encoder for the ctrlBlocks struct.
func ctrlBlockEncoder(w io.Writer, val any, _ *[8]byte) error {
if t, ok := val.(**ctrlBlocks); ok {
if t, ok := val.(*ctrlBlocks); ok {
return (*t).Encode(w)
}
@ -269,7 +272,7 @@ func ctrlBlockEncoder(w io.Writer, val any, _ *[8]byte) error {
// ctrlBlockDecoder is a custom TLV decoder for the ctrlBlocks struct.
func ctrlBlockDecoder(r io.Reader, val any, _ *[8]byte, l uint64) error {
if typ, ok := val.(**ctrlBlocks); ok {
if typ, ok := val.(*ctrlBlocks); ok {
ctrlReader := io.LimitReader(r, int64(l))
var ctrlBlocks ctrlBlocks
@ -278,7 +281,7 @@ func ctrlBlockDecoder(r io.Reader, val any, _ *[8]byte, l uint64) error {
return err
}
*typ = &ctrlBlocks
*typ = ctrlBlocks
return nil
}
@ -286,28 +289,6 @@ func ctrlBlockDecoder(r io.Reader, val any, _ *[8]byte, l uint64) error {
return tlv.NewTypeForDecodingErr(val, "ctrlBlocks", l, l)
}
// newCtrlBlocksRecord returns a new TLV record that can be used to
// encode/decode the set of cotrol blocks for the taproot outputs for a
// channel.
func newCtrlBlocksRecord(blks **ctrlBlocks) tlv.Record {
recordSize := func() uint64 {
var (
b bytes.Buffer
buf [8]byte
)
if err := ctrlBlockEncoder(&b, blks, &buf); err != nil {
panic(err)
}
return uint64(len(b.Bytes()))
}
return tlv.MakeDynamicRecord(
taprootCtrlBlockType, blks, recordSize, ctrlBlockEncoder,
ctrlBlockDecoder,
)
}
// EncodeRecords returns the set of TLV records that encode the control block
// for the commitment transaction.
func (c *ctrlBlocks) EncodeRecords() []tlv.Record {
@ -382,7 +363,21 @@ func (c *ctrlBlocks) DecodeRecords() []tlv.Record {
// Record returns a TLV record that can be used to encode/decode the control
// blocks. type from a given TLV stream.
func (c *ctrlBlocks) Record() tlv.Record {
return tlv.MakePrimitiveRecord(commitCtrlBlockType, c)
recordSize := func() uint64 {
var (
b bytes.Buffer
buf [8]byte
)
if err := ctrlBlockEncoder(&b, c, &buf); err != nil {
panic(err)
}
return uint64(len(b.Bytes()))
}
return tlv.MakeDynamicRecord(
0, c, recordSize, ctrlBlockEncoder, ctrlBlockDecoder,
)
}
// Encode encodes the set of control blocks.
@ -530,8 +525,8 @@ type tapTweaks struct {
}
// newTapTweaks returns a new tapTweaks struct.
func newTapTweaks() *tapTweaks {
return &tapTweaks{
func newTapTweaks() tapTweaks {
return tapTweaks{
BreachedHtlcTweaks: make(htlcTapTweaks),
BreachedSecondLevelHltcTweaks: make(htlcTapTweaks),
}
@ -539,7 +534,7 @@ func newTapTweaks() *tapTweaks {
// tapTweaksEncoder is a custom TLV encoder for the tapTweaks struct.
func tapTweaksEncoder(w io.Writer, val any, _ *[8]byte) error {
if t, ok := val.(**tapTweaks); ok {
if t, ok := val.(*tapTweaks); ok {
return (*t).Encode(w)
}
@ -548,7 +543,7 @@ func tapTweaksEncoder(w io.Writer, val any, _ *[8]byte) error {
// tapTweaksDecoder is a custom TLV decoder for the tapTweaks struct.
func tapTweaksDecoder(r io.Reader, val any, _ *[8]byte, l uint64) error {
if typ, ok := val.(**tapTweaks); ok {
if typ, ok := val.(*tapTweaks); ok {
tweakReader := io.LimitReader(r, int64(l))
var tapTweaks tapTweaks
@ -557,7 +552,7 @@ func tapTweaksDecoder(r io.Reader, val any, _ *[8]byte, l uint64) error {
return err
}
*typ = &tapTweaks
*typ = tapTweaks
return nil
}
@ -565,27 +560,6 @@ func tapTweaksDecoder(r io.Reader, val any, _ *[8]byte, l uint64) error {
return tlv.NewTypeForDecodingErr(val, "tapTweaks", l, l)
}
// newTapTweaksRecord returns a new TLV record that can be used to
// encode/decode the tap tweak structs.
func newTapTweaksRecord(tweaks **tapTweaks) tlv.Record {
recordSize := func() uint64 {
var (
b bytes.Buffer
buf [8]byte
)
if err := tapTweaksEncoder(&b, tweaks, &buf); err != nil {
panic(err)
}
return uint64(len(b.Bytes()))
}
return tlv.MakeDynamicRecord(
taprootTapTweakType, tweaks, recordSize, tapTweaksEncoder,
tapTweaksDecoder,
)
}
// EncodeRecords returns the set of TLV records that encode the tweaks.
func (t *tapTweaks) EncodeRecords() []tlv.Record {
var records []tlv.Record
@ -637,7 +611,21 @@ func (t *tapTweaks) DecodeRecords() []tlv.Record {
// Record returns a TLV record that can be used to encode/decode the tap
// tweaks.
func (t *tapTweaks) Record() tlv.Record {
return tlv.MakePrimitiveRecord(taprootTapTweakType, t)
recordSize := func() uint64 {
var (
b bytes.Buffer
buf [8]byte
)
if err := tapTweaksEncoder(&b, t, &buf); err != nil {
panic(err)
}
return uint64(len(b.Bytes()))
}
return tlv.MakeDynamicRecord(
0, t, recordSize, tapTweaksEncoder, tapTweaksDecoder,
)
}
// Encode encodes the set of tap tweaks.

View file

@ -5,6 +5,7 @@ import (
"math/rand"
"testing"
"github.com/lightningnetwork/lnd/tlv"
"github.com/stretchr/testify/require"
)
@ -70,18 +71,18 @@ func TestTaprootBriefcase(t *testing.T) {
require.NoError(t, err)
testCase := &taprootBriefcase{
CtrlBlocks: &ctrlBlocks{
CtrlBlocks: tlv.NewRecordT[tlv.TlvType0](ctrlBlocks{
CommitSweepCtrlBlock: sweepCtrlBlock[:],
RevokeSweepCtrlBlock: revokeCtrlBlock[:],
OutgoingHtlcCtrlBlocks: randResolverCtrlBlocks(t),
IncomingHtlcCtrlBlocks: randResolverCtrlBlocks(t),
SecondLevelCtrlBlocks: randResolverCtrlBlocks(t),
},
TapTweaks: &tapTweaks{
}),
TapTweaks: tlv.NewRecordT[tlv.TlvType1](tapTweaks{
AnchorTweak: anchorTweak[:],
BreachedHtlcTweaks: randHtlcTweaks(t),
BreachedSecondLevelHltcTweaks: randHtlcTweaks(t),
},
}),
}
var b bytes.Buffer