Skip to content

Commit d1f928f

Browse files
committed
WIP: fix TLV encoding/decoding
1 parent 56e2766 commit d1f928f

File tree

2 files changed

+63
-138
lines changed

2 files changed

+63
-138
lines changed

itest/rfq.go

+15-57
Original file line numberDiff line numberDiff line change
@@ -5,51 +5,33 @@ import (
55
"math/rand"
66
"time"
77

8-
"github.com/lightninglabs/taproot-assets/asset"
8+
"github.com/lightninglabs/taproot-assets/internal/test"
99
"github.com/lightninglabs/taproot-assets/rfqmessages"
1010
"github.com/lightningnetwork/lnd/lnrpc"
1111
"github.com/stretchr/testify/require"
1212
)
1313

1414
func testQuoteRequest(t *harnessTest) {
15+
// Ensure Alice and Bob are connected.
1516
t.lndHarness.EnsureConnected(t.lndHarness.Alice, t.lndHarness.Bob)
1617

17-
//t.Logf("Connecting LND nodes alice and bob")
18-
//aliceInfo := t.lndHarness.Bob.RPC.GetInfo()
19-
//
20-
//req := &lnrpc.ConnectPeerRequest{
21-
// Addr: &lnrpc.LightningAddress{
22-
// Pubkey: aliceInfo.IdentityPubkey,
23-
// Host: t.lndHarness.Bob.Cfg.P2PAddr(),
24-
// },
25-
//}
26-
//
27-
//ctxb := context.Background()
28-
//ctxt, cancel := context.WithTimeout(ctxb, defaultWaitTimeout)
29-
//defer cancel()
30-
//
31-
//_, err := t.lndHarness.Alice.RPC.LN.ConnectPeer(ctxt, req)
32-
//require.NoError(t.t, err, "unable to connect LND nodes alice and bob")
33-
34-
//t.Logf("Send an RFQ quote request from Bob to Alice")
35-
//aliceInfo := t.lndHarness.Alice.RPC.GetInfo()
36-
//
37-
//aliceIdPubKey, err := hex.DecodeString(aliceInfo.IdentityPubkey)
38-
//require.NoError(t.t, err, "unable to decode bob's pubkey")
39-
4018
// Generate a random quote request id.
4119
var randomQuoteRequestId [32]byte
4220
_, err := rand.Read(randomQuoteRequestId[:])
4321
require.NoError(t.t, err, "unable to generate random quote request id")
4422

45-
// Generate a random asset id.
46-
var randomAssetId asset.ID
47-
_, err = rand.Read(randomAssetId[:])
48-
require.NoError(t.t, err, "unable to generate random asset id")
23+
//// Generate a random asset id.
24+
//var randomAssetId asset.ID
25+
//_, err = rand.Read(randomAssetId[:])
26+
//require.NoError(t.t, err, "unable to generate random asset id")
27+
28+
// Generate a random asset group key.
29+
randomGroupPrivateKey := test.RandPrivKey(t.t)
4930

5031
quoteRequest := rfqmessages.QuoteRequest{
51-
ID: randomQuoteRequestId,
52-
AssetID: &randomAssetId,
32+
ID: randomQuoteRequestId,
33+
//AssetID: &randomAssetId,
34+
AssetGroupKey: randomGroupPrivateKey.PubKey(),
5335
AssetAmount: 42,
5436
SuggestedRateTick: 10,
5537
}
@@ -60,39 +42,15 @@ func testQuoteRequest(t *harnessTest) {
6042
require.NoError(t.t, err, "unable to encode quote request")
6143
quoteReqBytes := streamBuf.Bytes()
6244

63-
//go func() {
64-
// msgClient, cancel := t.lndHarness.Alice.RPC.SubscribeCustomMessages()
65-
// defer cancel()
66-
//
67-
// for {
68-
// msg, err := msgClient.Recv()
69-
// require.NoError(
70-
// t.t, err, "custom message receive: %w", err,
71-
// )
72-
//
73-
// t.Logf("Received custom message: %v", msg)
74-
// }
75-
//}()
76-
7745
resAlice := t.lndHarness.Alice.RPC.GetInfo()
78-
t.Logf("Alice alias: %s", resAlice.Alias)
79-
80-
resBob := t.lndHarness.Bob.RPC.GetInfo()
81-
t.Logf("Bob alias: %s", resBob.Alias)
82-
8346
t.Logf("Sending custom message to alias: %s", resAlice.Alias)
47+
8448
t.lndHarness.Bob.RPC.SendCustomMessage(&lnrpc.SendCustomMessageRequest{
8549
Peer: t.lndHarness.Alice.PubKey[:],
8650
Type: rfqmessages.MsgTypeQuoteRequest,
8751
Data: quoteReqBytes,
8852
})
8953

90-
//t.Logf("Sending custom message to alias: %s", resBob.Alias)
91-
//t.lndHarness.Alice.RPC.SendCustomMessage(&lnrpc.SendCustomMessageRequest{
92-
// Peer: t.lndHarness.Bob.PubKey[:],
93-
// Type: rfqmessages.MsgTypeQuoteRequest,
94-
// Data: quoteReqBytes,
95-
//})
96-
97-
time.Sleep(20 * time.Second)
54+
// Wait for Alice to receive the quote request.
55+
time.Sleep(5 * time.Second)
9856
}

rfqmessages/quote_request.go

+48-81
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package rfqmessages
22

33
import (
4-
"bytes"
5-
"encoding/binary"
6-
"fmt"
4+
"crypto/sha256"
75
"io"
86

97
"github.com/btcsuite/btcd/btcec/v2"
@@ -26,14 +24,51 @@ func QuoteRequestIDRecord(id *[32]byte) tlv.Record {
2624
return tlv.MakePrimitiveRecord(QuoteRequestIDType, id)
2725
}
2826

29-
func QuoteRequestAssetIDRecord(assetID *asset.ID) tlv.Record {
30-
assetIdBytes := assetID[:]
31-
return tlv.MakePrimitiveRecord(QuoteRequestAssetIDType, &assetIdBytes)
27+
func QuoteRequestAssetIDRecord(assetID **asset.ID) tlv.Record {
28+
const recordSize = sha256.Size
29+
30+
return tlv.MakeStaticRecord(
31+
QuoteRequestAssetIDType, assetID, recordSize,
32+
IDEncoder, IDDecoder,
33+
)
3234
}
3335

34-
func QuoteRequestGroupKeyRecord(groupKey *btcec.PublicKey) tlv.Record {
35-
return tlv.MakePrimitiveRecord(
36-
QuoteRequestGroupKeyType, &groupKey,
36+
func IDEncoder(w io.Writer, val any, buf *[8]byte) error {
37+
if t, ok := val.(**asset.ID); ok {
38+
id := [sha256.Size]byte(**t)
39+
return tlv.EBytes32(w, &id, buf)
40+
}
41+
42+
return tlv.NewTypeForEncodingErr(val, "AssetID")
43+
}
44+
45+
func IDDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error {
46+
const assetIDBytesLen = sha256.Size
47+
48+
if typ, ok := val.(**asset.ID); ok {
49+
var idBytes [assetIDBytesLen]byte
50+
51+
err := tlv.DBytes32(r, &idBytes, buf, assetIDBytesLen)
52+
if err != nil {
53+
return err
54+
}
55+
56+
id := asset.ID(idBytes)
57+
assetId := &id
58+
59+
*typ = assetId
60+
return nil
61+
}
62+
63+
return tlv.NewTypeForDecodingErr(val, "AssetID", l, sha256.Size)
64+
}
65+
66+
func QuoteRequestGroupKeyRecord(groupKey **btcec.PublicKey) tlv.Record {
67+
const recordSize = btcec.PubKeyBytesLenCompressed
68+
69+
return tlv.MakeStaticRecord(
70+
QuoteRequestGroupKeyType, groupKey, recordSize,
71+
asset.CompressedPubKeyEncoder, asset.CompressedPubKeyDecoder,
3772
)
3873
}
3974

@@ -91,11 +126,11 @@ func (q *QuoteRequest) EncodeRecords() []tlv.Record {
91126
records = append(records, QuoteRequestIDRecord(&q.ID))
92127

93128
if q.AssetID != nil {
94-
records = append(records, QuoteRequestAssetIDRecord(q.AssetID))
129+
records = append(records, QuoteRequestAssetIDRecord(&q.AssetID))
95130
}
96131

97132
if q.AssetGroupKey != nil {
98-
record := QuoteRequestGroupKeyRecord(q.AssetGroupKey)
133+
record := QuoteRequestGroupKeyRecord(&q.AssetGroupKey)
99134
records = append(records, record)
100135
}
101136

@@ -120,8 +155,8 @@ func (q *QuoteRequest) Encode(writer io.Writer) error {
120155
func (q *QuoteRequest) DecodeRecords() []tlv.Record {
121156
return []tlv.Record{
122157
QuoteRequestIDRecord(&q.ID),
123-
QuoteRequestAssetIDRecord(q.AssetID),
124-
QuoteRequestGroupKeyRecord(q.AssetGroupKey),
158+
QuoteRequestAssetIDRecord(&q.AssetID),
159+
QuoteRequestGroupKeyRecord(&q.AssetGroupKey),
125160
QuoteRequestAssetAmountRecord(&q.AssetAmount),
126161
QuoteRequestAmtCharacteristicRecord(&q.SuggestedRateTick),
127162
}
@@ -135,71 +170,3 @@ func (q *QuoteRequest) Decode(r io.Reader) error {
135170
}
136171
return stream.Decode(r)
137172
}
138-
139-
// EncodeNonTlv serializes the QuoteRequest struct into a byte slice.
140-
func (q *QuoteRequest) EncodeNonTlv() ([]byte, error) {
141-
buf := new(bytes.Buffer)
142-
143-
_, err := buf.Write(q.ID[:])
144-
if err != nil {
145-
return nil, err
146-
}
147-
148-
_, err = buf.Write(q.AssetID[:])
149-
if err != nil {
150-
return nil, err
151-
}
152-
153-
var groupKeyBytes [33]byte
154-
if q.AssetGroupKey != nil {
155-
k := q.AssetGroupKey.SerializeCompressed()
156-
copy(groupKeyBytes[:], k)
157-
}
158-
_, err = buf.Write(groupKeyBytes[:])
159-
if err != nil {
160-
return nil, err
161-
}
162-
163-
err = binary.Write(buf, binary.BigEndian, q.AssetAmount)
164-
if err != nil {
165-
return nil, err
166-
}
167-
168-
err = binary.Write(buf, binary.BigEndian, q.SuggestedRateTick)
169-
if err != nil {
170-
return nil, err
171-
}
172-
173-
return buf.Bytes(), nil
174-
}
175-
176-
// DecodeNonTlv populates a QuoteRequest instance from a byte slice
177-
func (q *QuoteRequest) DecodeNonTlv(data []byte) error {
178-
if len(data) != 113 {
179-
return fmt.Errorf("invalid data length")
180-
}
181-
182-
var err error
183-
184-
// Parse the request's ID.
185-
copy(q.ID[:], data[:32])
186-
187-
// Parse the asset's ID.
188-
copy(q.AssetID[:], data[32:64])
189-
190-
// Parse the asset's compressed public group key.
191-
var compressedPubGroupKeyBytes []byte
192-
copy(compressedPubGroupKeyBytes[:], data[64:97])
193-
q.AssetGroupKey, err = btcec.ParsePubKey(
194-
compressedPubGroupKeyBytes,
195-
)
196-
if err != nil {
197-
return fmt.Errorf("unable to parse compressed public group "+
198-
"key: %w", err)
199-
}
200-
201-
q.AssetAmount = binary.BigEndian.Uint64(data[97:105])
202-
q.SuggestedRateTick = binary.BigEndian.Uint64(data[105:])
203-
204-
return nil
205-
}

0 commit comments

Comments
 (0)