Skip to content

Commit

Permalink
multi: encode/decode keys with their parity byte
Browse files Browse the repository at this point in the history
  • Loading branch information
jharveyb committed Nov 4, 2022
1 parent a1ed596 commit 249b8a9
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 58 deletions.
21 changes: 10 additions & 11 deletions address/encoding.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,31 @@ import (
"io"

"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/schnorr"
"github.com/lightningnetwork/lnd/tlv"
)

func schnorrPubKeyEncoder(w io.Writer, val any, buf *[8]byte) error {
func compressedPubKeyEncoder(w io.Writer, val any, buf *[8]byte) error {
if t, ok := val.(*btcec.PublicKey); ok {
var keyBytes [schnorr.PubKeyBytesLen]byte
copy(keyBytes[:], schnorr.SerializePubKey(t))
return tlv.EBytes32(w, &keyBytes, buf)
var keyBytes [btcec.PubKeyBytesLenCompressed]byte
copy(keyBytes[:], t.SerializeCompressed())
return tlv.EBytes33(w, &keyBytes, buf)
}
return tlv.NewTypeForEncodingErr(val, "*btcec.PublicKey")
}

func schnorrPubKeyDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error {
func compressedPubKeyDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error {
if typ, ok := val.(*btcec.PublicKey); ok {
var keyBytes [schnorr.PubKeyBytesLen]byte
err := tlv.DBytes32(r, &keyBytes, buf, schnorr.PubKeyBytesLen)
var keyBytes [btcec.PubKeyBytesLenCompressed]byte
err := tlv.DBytes33(r, &keyBytes, buf, btcec.PubKeyBytesLenCompressed)
if err != nil {
return err
}
var key *btcec.PublicKey
// Handle empty key, which is not on the curve.
if keyBytes == [32]byte{} {
if keyBytes == [btcec.PubKeyBytesLenCompressed]byte{} {
key = &btcec.PublicKey{}
} else {
key, err = schnorr.ParsePubKey(keyBytes[:])
key, err = btcec.ParsePubKey(keyBytes[:])
if err != nil {
return err
}
Expand All @@ -38,6 +37,6 @@ func schnorrPubKeyDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error {
return nil
}
return tlv.NewTypeForDecodingErr(
val, "*btcec.PublicKey", l, schnorr.PubKeyBytesLen,
val, "*btcec.PublicKey", l, btcec.PubKeyBytesLenCompressed,
)
}
13 changes: 6 additions & 7 deletions address/records.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"bytes"

"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/schnorr"
"github.com/lightninglabs/taro/asset"
"github.com/lightningnetwork/lnd/tlv"
)
Expand Down Expand Up @@ -58,22 +57,22 @@ func newAddressGenesisRecord(genesis *asset.Genesis) tlv.Record {

func newAddressFamilyKeyRecord(familyKey **btcec.PublicKey) tlv.Record {
return tlv.MakeStaticRecord(
addrFamKeyType, familyKey, schnorr.PubKeyBytesLen,
asset.SchnorrPubKeyEncoder, asset.SchnorrPubKeyDecoder,
addrFamKeyType, familyKey, btcec.PubKeyBytesLenCompressed,
asset.CompressedPubKeyEncoder, asset.CompressedPubKeyDecoder,
)
}

func newAddressScriptKeyRecord(scriptKey *btcec.PublicKey) tlv.Record {
return tlv.MakeStaticRecord(
addrScriptKeyType, scriptKey, schnorr.PubKeyBytesLen,
schnorrPubKeyEncoder, schnorrPubKeyDecoder,
addrScriptKeyType, scriptKey, btcec.PubKeyBytesLenCompressed,
compressedPubKeyEncoder, compressedPubKeyDecoder,
)
}

func newAddressInternalKeyRecord(internalKey *btcec.PublicKey) tlv.Record {
return tlv.MakeStaticRecord(
addrInternalKeyType, internalKey, schnorr.PubKeyBytesLen,
schnorrPubKeyEncoder, schnorrPubKeyDecoder,
addrInternalKeyType, internalKey, btcec.PubKeyBytesLenCompressed,
compressedPubKeyEncoder, compressedPubKeyDecoder,
)
}

Expand Down
4 changes: 2 additions & 2 deletions asset/asset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ var (
hashBytes1 = [32]byte{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
hashBytes2 = [32]byte{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}
pubKeyBytes, _ = hex.DecodeString(
"a0afeb165f0ec36880b68e0baabd9ad9c62fd1a69aa998bc30e9a346202e078f",
"03a0afeb165f0ec36880b68e0baabd9ad9c62fd1a69aa998bc30e9a346202e078f",
)
pubKey, _ = schnorr.ParsePubKey(pubKeyBytes)
pubKey, _ = btcec.ParsePubKey(pubKeyBytes)
sigBytes, _ = hex.DecodeString(
"e907831f80848d1069a5371b402410364bdf1c5f8307b0084c55f1ce2dca821525f66a4a85ea8b71e482a74f382d2ce5ebeee8fdb2172f477df4900d310536c0",
)
Expand Down
55 changes: 26 additions & 29 deletions asset/encoding.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,28 +106,28 @@ func OutPointDecoder(r io.Reader, val any, buf *[8]byte, _ uint64) error {
return tlv.NewTypeForEncodingErr(val, "wire.OutPoint")
}

func SchnorrPubKeyEncoder(w io.Writer, val any, buf *[8]byte) error {
func CompressedPubKeyEncoder(w io.Writer, val any, buf *[8]byte) error {
if t, ok := val.(**btcec.PublicKey); ok {
var keyBytes [schnorr.PubKeyBytesLen]byte
copy(keyBytes[:], schnorr.SerializePubKey(*t))
return tlv.EBytes32(w, &keyBytes, buf)
var keyBytes [btcec.PubKeyBytesLenCompressed]byte
copy(keyBytes[:], (*t).SerializeCompressed())
return tlv.EBytes33(w, &keyBytes, buf)
}
return tlv.NewTypeForEncodingErr(val, "*btcec.PublicKey")
}

func SchnorrPubKeyDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error {
func CompressedPubKeyDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error {
if typ, ok := val.(**btcec.PublicKey); ok {
var keyBytes [schnorr.PubKeyBytesLen]byte
err := tlv.DBytes32(r, &keyBytes, buf, schnorr.PubKeyBytesLen)
var keyBytes [btcec.PubKeyBytesLenCompressed]byte
err := tlv.DBytes33(r, &keyBytes, buf, btcec.PubKeyBytesLenCompressed)
if err != nil {
return err
}
var key *btcec.PublicKey
// Handle empty key, which is not on the curve.
if keyBytes == [32]byte{} {
if keyBytes == [btcec.PubKeyBytesLenCompressed]byte{} {
key = &btcec.PublicKey{}
} else {
key, err = schnorr.ParsePubKey(keyBytes[:])
key, err = btcec.ParsePubKey(keyBytes[:])
if err != nil {
return err
}
Expand All @@ -136,7 +136,7 @@ func SchnorrPubKeyDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error {
return nil
}
return tlv.NewTypeForDecodingErr(
val, "*btcec.PublicKey", l, schnorr.PubKeyBytesLen,
val, "*btcec.PublicKey", l, btcec.PubKeyBytesLenCompressed,
)
}

Expand Down Expand Up @@ -208,41 +208,38 @@ func IDDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error {
return tlv.NewTypeForDecodingErr(val, "ID", l, sha256.Size)
}

func SchnorrSerializedKeyEncoder(w io.Writer, val any, buf *[8]byte) error {
func SerializedKeyEncoder(w io.Writer, val any, buf *[8]byte) error {
if t, ok := val.(*SerializedKey); ok {
id := [33]byte(*t)
id := [btcec.PubKeyBytesLenCompressed]byte(*t)

// We need the Schnorr, 32-byte x-only encoding here, skip the
// first byte that contains the parity information.
xOnly := id[1:]
return tlv.EVarBytes(w, &xOnly, buf)
withParity := id[:]
return tlv.EVarBytes(w, &withParity, buf)
}
return tlv.NewTypeForEncodingErr(val, "SerializedKey")
}

func SchnorrSerializedKeyDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error {
func SerializedKeyDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error {
if typ, ok := val.(*SerializedKey); ok {
// The key is stored in the Schnorr, 32-byte x-only format.
var keyBytes [schnorr.PubKeyBytesLen]byte
err := tlv.DBytes32(r, &keyBytes, buf, schnorr.PubKeyBytesLen)
var keyBytes [btcec.PubKeyBytesLenCompressed]byte
err := tlv.DBytes33(r, &keyBytes, buf, btcec.PubKeyBytesLenCompressed)
if err != nil {
return err
}

// Handle empty key, which is not on the curve.
if keyBytes == [32]byte{} {
if keyBytes == [btcec.PubKeyBytesLenCompressed]byte{} {
*typ = SerializedKey{}
return nil
}

pubKey, err := schnorr.ParsePubKey(keyBytes[:])
pubKey, err := btcec.ParsePubKey(keyBytes[:])
if err != nil {
return err
}
*typ = ToSerialized(pubKey)
return nil
}
return tlv.NewTypeForDecodingErr(val, "SerializedKey", l, 33)
return tlv.NewTypeForDecodingErr(val, "SerializedKey", l, btcec.PubKeyBytesLenCompressed)
}

func TypeEncoder(w io.Writer, val any, buf *[8]byte) error {
Expand Down Expand Up @@ -323,7 +320,7 @@ func PrevIDEncoder(w io.Writer, val any, buf *[8]byte) error {
if err := IDEncoder(w, &(**t).ID, buf); err != nil {
return err
}
return SchnorrSerializedKeyEncoder(w, &(**t).ScriptKey, buf)
return SerializedKeyEncoder(w, &(**t).ScriptKey, buf)
}
return tlv.NewTypeForEncodingErr(val, "*PrevID")
}
Expand All @@ -338,8 +335,8 @@ func PrevIDDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error {
if err = IDDecoder(r, &prevID.ID, buf, sha256.Size); err != nil {
return err
}
if err = SchnorrSerializedKeyDecoder(
r, &prevID.ScriptKey, buf, 33,
if err = SerializedKeyDecoder(
r, &prevID.ScriptKey, buf, btcec.PubKeyBytesLenCompressed,
); err != nil {
return err
}
Expand Down Expand Up @@ -557,7 +554,7 @@ func ScriptVersionDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error {
func FamilyKeyEncoder(w io.Writer, val any, buf *[8]byte) error {
if t, ok := val.(**FamilyKey); ok {
key := &(*t).FamKey
if err := SchnorrPubKeyEncoder(w, &key, buf); err != nil {
if err := CompressedPubKeyEncoder(w, &key, buf); err != nil {
return err
}
sig := (*t).Sig
Expand All @@ -572,8 +569,8 @@ func FamilyKeyDecoder(r io.Reader, val any, buf *[8]byte, _ uint64) error {
familyKey FamilyKey
famKey *btcec.PublicKey
)
err := SchnorrPubKeyDecoder(
r, &famKey, buf, schnorr.PubKeyBytesLen,
err := CompressedPubKeyDecoder(
r, &famKey, buf, btcec.PubKeyBytesLenCompressed,
)
if err != nil {
return err
Expand Down
12 changes: 6 additions & 6 deletions asset/records.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,15 @@ func NewLeafScriptVersionRecord(version *ScriptVersion) tlv.Record {
}

func NewLeafScriptKeyRecord(scriptKey **btcec.PublicKey) tlv.Record {
const recordSize = schnorr.PubKeyBytesLen
const recordSize = btcec.PubKeyBytesLenCompressed
return tlv.MakeStaticRecord(
LeafScriptKey, scriptKey, recordSize,
SchnorrPubKeyEncoder, SchnorrPubKeyDecoder,
CompressedPubKeyEncoder, CompressedPubKeyDecoder,
)
}

func NewLeafFamilyKeyRecord(familyKey **FamilyKey) tlv.Record {
const recordSize = schnorr.PubKeyBytesLen + schnorr.SignatureSize
const recordSize = btcec.PubKeyBytesLenCompressed + schnorr.SignatureSize
return tlv.MakeStaticRecord(
LeafFamilyKey, familyKey, recordSize, FamilyKeyEncoder,
FamilyKeyDecoder,
Expand All @@ -153,13 +153,13 @@ func NewLeafFamilyKeyRecord(familyKey **FamilyKey) tlv.Record {

func NewLeafFamilyKeyOnlyRecord(familyKey **btcec.PublicKey) tlv.Record {
return tlv.MakeStaticRecord(
LeafFamilyKey, familyKey, schnorr.PubKeyBytesLen,
SchnorrPubKeyEncoder, SchnorrPubKeyDecoder,
LeafFamilyKey, familyKey, btcec.PubKeyBytesLenCompressed,
CompressedPubKeyEncoder, CompressedPubKeyDecoder,
)
}

func NewWitnessPrevIDRecord(prevID **PrevID) tlv.Record {
const recordSize = 36 + sha256.Size + schnorr.PubKeyBytesLen
const recordSize = 36 + sha256.Size + btcec.PubKeyBytesLenCompressed
return tlv.MakeStaticRecord(
WitnessPrevID, prevID, recordSize, PrevIDEncoder, PrevIDDecoder,
)
Expand Down
6 changes: 3 additions & 3 deletions proof/records.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"bytes"

"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcec/v2/schnorr"
"github.com/btcsuite/btcd/wire"
"github.com/lightninglabs/taro/asset"
"github.com/lightninglabs/taro/commitment"
Expand Down Expand Up @@ -161,8 +160,9 @@ func TaprootProofOutputIndexRecord(idx *uint32) tlv.Record {

func TaprootProofInternalKeyRecord(internalKey **btcec.PublicKey) tlv.Record {
return tlv.MakeStaticRecord(
TaprootProofInternalKeyType, internalKey, schnorr.PubKeyBytesLen,
asset.SchnorrPubKeyEncoder, asset.SchnorrPubKeyDecoder,
TaprootProofInternalKeyType, internalKey,
btcec.PubKeyBytesLenCompressed,
asset.CompressedPubKeyEncoder, asset.CompressedPubKeyDecoder,
)
}

Expand Down

0 comments on commit 249b8a9

Please sign in to comment.