Skip to content

Commit 7436356

Browse files
committed
proof: add SendFragment and SendFragmentEnvelope types
We need to place these types in the proof package because the proof courier will need access to them. And because we already use the proof package from the address package, we can't place the new types there, as that would create a circular package dependency.
1 parent 704dbc9 commit 7436356

File tree

4 files changed

+525
-0
lines changed

4 files changed

+525
-0
lines changed

proof/encoding.go

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -739,3 +739,136 @@ func PublicKeyOptionDecoder(r io.Reader, val any, buf *[8]byte,
739739
val, "*fn.Option[btcec.PublicKey]", l, l,
740740
)
741741
}
742+
743+
func FragmentVersionEncoder(w io.Writer, val any, buf *[8]byte) error {
744+
if t, ok := val.(*SendFragmentVersion); ok {
745+
return tlv.EUint8T(w, uint8(*t), buf)
746+
}
747+
return tlv.NewTypeForEncodingErr(val, "SendFragmentVersion")
748+
}
749+
750+
func FragmentVersionDecoder(r io.Reader, val any, buf *[8]byte,
751+
l uint64) error {
752+
753+
if typ, ok := val.(*SendFragmentVersion); ok {
754+
var t uint8
755+
if err := tlv.DUint8(r, &t, buf, l); err != nil {
756+
return err
757+
}
758+
*typ = SendFragmentVersion(t)
759+
return nil
760+
}
761+
return tlv.NewTypeForDecodingErr(val, "SendFragmentVersion", l, 1)
762+
}
763+
764+
func SendOutputEncoder(w io.Writer, val any, buf *[8]byte) error {
765+
if t, ok := val.(*SendOutput); ok {
766+
err := tlv.EUint8T(w, uint8(t.AssetVersion), buf)
767+
if err != nil {
768+
return err
769+
}
770+
if err := tlv.EUint64T(w, t.Amount, buf); err != nil {
771+
return err
772+
}
773+
err = tlv.EUint8T(w, uint8(t.DerivationMethod), buf)
774+
if err != nil {
775+
return err
776+
}
777+
778+
keyArr := ([btcec.PubKeyBytesLenCompressed]byte)(t.ScriptKey)
779+
return tlv.EBytes33(w, &keyArr, buf)
780+
}
781+
return tlv.NewTypeForEncodingErr(val, "*SendOutput")
782+
}
783+
784+
func SendOutputDecoder(r io.Reader, val any, buf *[8]byte) error {
785+
if typ, ok := val.(*SendOutput); ok {
786+
var assetVersion uint8
787+
if err := tlv.DUint8(r, &assetVersion, buf, 1); err != nil {
788+
return err
789+
}
790+
typ.AssetVersion = asset.Version(assetVersion)
791+
792+
if err := tlv.DUint64(r, &typ.Amount, buf, 8); err != nil {
793+
return err
794+
}
795+
796+
var derivationMethod uint8
797+
if err := tlv.DUint8(r, &derivationMethod, buf, 1); err != nil {
798+
return err
799+
}
800+
typ.DerivationMethod = asset.ScriptKeyDerivationMethod(
801+
derivationMethod,
802+
)
803+
804+
keyArr := ([btcec.PubKeyBytesLenCompressed]byte)(typ.ScriptKey)
805+
if err := tlv.DBytes33(
806+
r, &keyArr, buf, btcec.PubKeyBytesLenCompressed,
807+
); err != nil {
808+
return err
809+
}
810+
typ.ScriptKey = keyArr
811+
812+
return nil
813+
}
814+
return tlv.NewTypeForEncodingErr(val, "*SendOutput")
815+
}
816+
817+
func SendOutputsEncoder(w io.Writer, val any, buf *[8]byte) error {
818+
if t, ok := val.(*map[asset.ID]SendOutput); ok {
819+
numOutputs := uint64(len(*t))
820+
if err := tlv.WriteVarInt(w, numOutputs, buf); err != nil {
821+
return err
822+
}
823+
824+
for id, output := range *t {
825+
idArr := ([32]byte)(id)
826+
if err := tlv.EBytes32(w, &idArr, buf); err != nil {
827+
return err
828+
}
829+
830+
err := SendOutputEncoder(w, &output, buf)
831+
if err != nil {
832+
return err
833+
}
834+
}
835+
return nil
836+
}
837+
return tlv.NewTypeForEncodingErr(val, "map[asset.ID]SendOutput")
838+
}
839+
840+
func SendOutputsDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error {
841+
if typ, ok := val.(*map[asset.ID]SendOutput); ok {
842+
numOutputs, err := tlv.ReadVarInt(r, buf)
843+
if err != nil {
844+
return err
845+
}
846+
847+
// Avoid OOM by limiting the number of send outputs we accept.
848+
if numOutputs > MaxSendFragmentOutputs {
849+
return fmt.Errorf("%w: too many send outputs",
850+
ErrProofInvalid)
851+
}
852+
853+
result := make(map[asset.ID]SendOutput, numOutputs)
854+
for i := uint64(0); i < numOutputs; i++ {
855+
var id [32]byte
856+
if err := tlv.DBytes32(r, &id, buf, 32); err != nil {
857+
return err
858+
}
859+
860+
var output SendOutput
861+
err := SendOutputDecoder(r, &output, buf)
862+
if err != nil {
863+
return err
864+
}
865+
866+
result[id] = output
867+
}
868+
869+
*typ = result
870+
871+
return nil
872+
}
873+
return tlv.NewTypeForEncodingErr(val, "map[asset.ID]SendOutput")
874+
}

proof/records.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package proof
22

33
import (
44
"bytes"
5+
"crypto/sha256"
56
"net/url"
67

78
"github.com/btcsuite/btcd/btcec/v2"
@@ -54,6 +55,29 @@ const (
5455
MetaRevealUniverseCommitments tlv.Type = 7
5556
MetaRevealCanonicalUniversesType tlv.Type = 9
5657
MetaRevealDelegationKeyType tlv.Type = 11
58+
59+
// SendFragmentVersionType is the TLV type of the send fragment version.
60+
SendFragmentVersionType tlv.Type = 0
61+
62+
// SendFragmentBlockHeaderType is the TLV type of the send fragment's
63+
// block header.
64+
SendFragmentBlockHeaderType tlv.Type = 2
65+
66+
// SendFragmentBlockHeightType is the TLV type of the send fragment's
67+
// block height.
68+
SendFragmentBlockHeightType tlv.Type = 4
69+
70+
// SendFragmentOutPointType is the TLV type of the send fragment's
71+
// outpoint.
72+
SendFragmentOutPointType tlv.Type = 6
73+
74+
// SendFragmentOutputsType is the TLV type of the send fragment's
75+
// outputs.
76+
SendFragmentOutputsType tlv.Type = 8
77+
78+
// SendFragmentTaprootAssetRootType is the TLV type of the send
79+
// fragment's Taproot Asset root. This is used to
80+
SendFragmentTaprootAssetRootType tlv.Type = 10
5781
)
5882

5983
// KnownProofTypes is a set of all known proof TLV types. This set is asserted
@@ -97,6 +121,15 @@ var KnownMetaRevealTypes = fn.NewSet(
97121
MetaRevealDelegationKeyType,
98122
)
99123

124+
// KnownSendFragmentTypes is a set of all known send fragment TLV types.
125+
// This set is asserted to be complete by a check in the BIP test vector unit
126+
// tests.
127+
var KnownSendFragmentTypes = fn.NewSet(
128+
SendFragmentVersionType, SendFragmentBlockHeaderType,
129+
SendFragmentBlockHeightType, SendFragmentOutPointType,
130+
SendFragmentOutputsType, SendFragmentTaprootAssetRootType,
131+
)
132+
100133
func VersionRecord(version *TransitionVersion) tlv.Record {
101134
return tlv.MakeStaticRecord(
102135
VersionType, version, 4, VersionEncoder, VersionDecoder,
@@ -514,3 +547,53 @@ func AltLeavesRecord(leaves *[]asset.AltLeaf[asset.Asset]) tlv.Record {
514547
asset.AltLeavesDecoder,
515548
)
516549
}
550+
551+
func FragmentVersionRecord(version *SendFragmentVersion) tlv.Record {
552+
return tlv.MakeStaticRecord(
553+
SendFragmentVersionType, version, 1, FragmentVersionEncoder,
554+
FragmentVersionDecoder,
555+
)
556+
}
557+
558+
func FragmentBlockHeaderRecord(header *wire.BlockHeader) tlv.Record {
559+
return tlv.MakeStaticRecord(
560+
SendFragmentBlockHeaderType, header, wire.MaxBlockHeaderPayload,
561+
BlockHeaderEncoder, BlockHeaderDecoder,
562+
)
563+
}
564+
565+
func FragmentBlockHeightRecord(height *uint32) tlv.Record {
566+
return tlv.MakeStaticRecord(
567+
SendFragmentBlockHeightType, height, 4, tlv.EUint32,
568+
tlv.DUint32,
569+
)
570+
}
571+
572+
func FragmentOutPointRecord(prevOut *wire.OutPoint) tlv.Record {
573+
return tlv.MakeStaticRecord(
574+
SendFragmentOutPointType, prevOut, 32+4, asset.OutPointEncoder,
575+
asset.OutPointDecoder,
576+
)
577+
}
578+
579+
func FragmentOutputsRecord(outputs *map[asset.ID]SendOutput) tlv.Record {
580+
sizeFunc := func() uint64 {
581+
var buf bytes.Buffer
582+
err := SendOutputsEncoder(&buf, outputs, &[8]byte{})
583+
if err != nil {
584+
panic(err)
585+
}
586+
return uint64(len(buf.Bytes()))
587+
}
588+
return tlv.MakeDynamicRecord(
589+
SendFragmentOutputsType, outputs, sizeFunc, SendOutputsEncoder,
590+
SendOutputsDecoder,
591+
)
592+
}
593+
594+
func FragmentTaprootAssetRootRecord(root *[sha256.Size]byte) tlv.Record {
595+
return tlv.MakeStaticRecord(
596+
SendFragmentTaprootAssetRootType, root, sha256.Size,
597+
tlv.EBytes32, tlv.DBytes32,
598+
)
599+
}

0 commit comments

Comments
 (0)