-
Notifications
You must be signed in to change notification settings - Fork 121
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
277 additions
and
167 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,144 +1,174 @@ | ||
package rfqmessages | ||
|
||
import ( | ||
"crypto/sha256" | ||
"bytes" | ||
"fmt" | ||
"io" | ||
|
||
"github.com/btcsuite/btcd/btcec/v2" | ||
"github.com/lightninglabs/taproot-assets/asset" | ||
"github.com/lightninglabs/lndclient" | ||
"github.com/lightningnetwork/lnd/routing/route" | ||
"github.com/lightningnetwork/lnd/tlv" | ||
) | ||
|
||
const ( | ||
// QuoteAccept field TLV types. | ||
// QuoteAcceptMsgData field TLV types. | ||
|
||
QuoteAcceptIDType tlv.Type = 0 | ||
QuoteAcceptAssetIDType tlv.Type = 1 | ||
QuoteAcceptGroupKeyType tlv.Type = 3 | ||
QuoteAcceptAssetAmountType tlv.Type = 4 | ||
QuoteAcceptAmtCharacteristicType tlv.Type = 6 | ||
QuoteAcceptMsgDataIDType tlv.Type = 0 | ||
QuoteAcceptMsgDataCharacteristicType tlv.Type = 2 | ||
QuoteAcceptMsgDataExpiryType tlv.Type = 4 | ||
QuoteAcceptMsgDataSignatureType tlv.Type = 6 | ||
) | ||
|
||
func QuoteAcceptIDRecord(id *[32]byte) tlv.Record { | ||
return tlv.MakePrimitiveRecord(QuoteAcceptIDType, id) | ||
func QuoteAcceptMsgDataIDRecord(id *ID) tlv.Record { | ||
return tlv.MakePrimitiveRecord(QuoteAcceptMsgDataIDType, id) | ||
} | ||
|
||
func QuoteAcceptAssetIDRecord(assetID **asset.ID) tlv.Record { | ||
const recordSize = sha256.Size | ||
|
||
return tlv.MakeStaticRecord( | ||
QuoteAcceptAssetIDType, assetID, recordSize, | ||
IDEncoder, IDDecoder, | ||
func QuoteAcceptMsgDataCharacteristicRecord(characteristic *uint64) tlv.Record { | ||
return tlv.MakePrimitiveRecord( | ||
QuoteAcceptMsgDataCharacteristicType, characteristic, | ||
) | ||
} | ||
|
||
func QuoteAcceptGroupKeyRecord(groupKey **btcec.PublicKey) tlv.Record { | ||
const recordSize = btcec.PubKeyBytesLenCompressed | ||
|
||
return tlv.MakeStaticRecord( | ||
QuoteAcceptGroupKeyType, groupKey, recordSize, | ||
asset.CompressedPubKeyEncoder, asset.CompressedPubKeyDecoder, | ||
func QuoteAcceptMsgDataExpiryRecord(expirySeconds *uint64) tlv.Record { | ||
return tlv.MakePrimitiveRecord( | ||
QuoteAcceptMsgDataExpiryType, expirySeconds, | ||
) | ||
} | ||
|
||
func QuoteAcceptAssetAmountRecord(assetAmount *uint64) tlv.Record { | ||
return tlv.MakePrimitiveRecord(QuoteAcceptAssetAmountType, assetAmount) | ||
} | ||
|
||
func QuoteAcceptAmtCharacteristicRecord(amtCharacteristic *uint64) tlv.Record { | ||
func QuoteAcceptMsgDataSig(sig *[64]byte) tlv.Record { | ||
return tlv.MakePrimitiveRecord( | ||
QuoteAcceptAmtCharacteristicType, amtCharacteristic, | ||
QuoteAcceptMsgDataSignatureType, sig, | ||
) | ||
} | ||
|
||
// QuoteAccept is a struct that represents a request for a quote (RFQ) from a | ||
// QuoteAcceptMsgData is a struct that represents a request for a quote (RFQ) from a | ||
// peer. | ||
type QuoteAccept struct { | ||
type QuoteAcceptMsgData struct { | ||
// ID is the unique identifier of the request for quote (RFQ). | ||
ID [32]byte | ||
|
||
// // AssetID represents the identifier of the asset for which the peer | ||
// is requesting a quote. | ||
AssetID *asset.ID | ||
ID ID | ||
|
||
// AssetGroupKey is the public group key of the asset for which the peer | ||
// is requesting a quote. | ||
AssetGroupKey *btcec.PublicKey | ||
// AmtCharacteristic is the characteristic of the asset amount that | ||
// determines the fee rate. | ||
AmtCharacteristic uint64 | ||
|
||
// AssetAmount is the amount of the asset for which the peer is | ||
// requesting a quote. | ||
AssetAmount uint64 | ||
// ExpirySeconds is the number of seconds until the quote expires. | ||
ExpirySeconds uint64 | ||
|
||
// TODO(ffranr): rename to AmtCharacteristic? | ||
SuggestedRateTick uint64 | ||
// Sig is a signature over the serialized contents of the message. | ||
Sig [64]byte | ||
} | ||
|
||
// Validate ensures that the quote request is valid. | ||
func (q *QuoteAccept) Validate() error { | ||
if q.AssetID == nil && q.AssetGroupKey == nil { | ||
return fmt.Errorf("asset id and group key cannot both be nil") | ||
} | ||
|
||
if q.AssetID != nil && q.AssetGroupKey != nil { | ||
return fmt.Errorf("asset id and group key cannot both be " + | ||
"non-nil") | ||
} | ||
|
||
return nil | ||
} | ||
//func NewQuoteAcceptMsgData(q *QuoteAccept) (*QuoteAcceptMsgData, error) { | ||
// // Hash the fields of the message data so that we can create a signature | ||
// // over the message. | ||
// h := sha256.New() | ||
// | ||
// _, err := h.Write(q.ID[:]) | ||
// if err != nil { | ||
// return nil, err | ||
// } | ||
// | ||
// err = binary.Write(h, binary.BigEndian, q.AmtCharacteristic) | ||
// if err != nil { | ||
// return nil, err | ||
// } | ||
// | ||
// err = binary.Write(h, binary.BigEndian, q.ExpirySeconds) | ||
// if err != nil { | ||
// return nil, err | ||
// } | ||
// | ||
// // TODO(ffranr): Sign the hash of the message data. | ||
// //fieldsHash := h.Sum(nil) | ||
// //sig | ||
// | ||
// return &QuoteAcceptMsgData{ | ||
// ID: q.ID, | ||
// AmtCharacteristic: q.AmtCharacteristic, | ||
// ExpirySeconds: q.ExpirySeconds, | ||
// //Sig: sig, | ||
// }, nil | ||
//} | ||
|
||
// EncodeRecords determines the non-nil records to include when encoding an | ||
// asset witness at runtime. | ||
func (q *QuoteAccept) EncodeRecords() []tlv.Record { | ||
func (q *QuoteAcceptMsgData) encodeRecords() []tlv.Record { | ||
var records []tlv.Record | ||
|
||
records = append(records, QuoteAcceptIDRecord(&q.ID)) | ||
|
||
if q.AssetID != nil { | ||
records = append(records, QuoteAcceptAssetIDRecord(&q.AssetID)) | ||
} | ||
// Add ID record. | ||
records = append(records, QuoteAcceptMsgDataIDRecord(&q.ID)) | ||
|
||
if q.AssetGroupKey != nil { | ||
record := QuoteAcceptGroupKeyRecord(&q.AssetGroupKey) | ||
records = append(records, record) | ||
} | ||
// Add characteristic record. | ||
record := QuoteAcceptMsgDataCharacteristicRecord( | ||
&q.AmtCharacteristic, | ||
) | ||
records = append(records, record) | ||
|
||
records = append(records, QuoteAcceptAssetAmountRecord(&q.AssetAmount)) | ||
// Add expiry record. | ||
records = append( | ||
records, QuoteAcceptMsgDataExpiryRecord(&q.ExpirySeconds), | ||
) | ||
|
||
record := QuoteAcceptAmtCharacteristicRecord(&q.SuggestedRateTick) | ||
records = append(records, record) | ||
// Add signature record. | ||
records = append( | ||
records, QuoteAcceptMsgDataSig(&q.Sig), | ||
) | ||
|
||
return records | ||
} | ||
|
||
// Encode encodes the structure into a TLV stream. | ||
func (q *QuoteAccept) Encode(writer io.Writer) error { | ||
stream, err := tlv.NewStream(q.EncodeRecords()...) | ||
func (q *QuoteAcceptMsgData) Encode(writer io.Writer) error { | ||
stream, err := tlv.NewStream(q.encodeRecords()...) | ||
if err != nil { | ||
return err | ||
} | ||
return stream.Encode(writer) | ||
} | ||
|
||
// DecodeRecords provides all TLV records for decoding. | ||
func (q *QuoteAccept) DecodeRecords() []tlv.Record { | ||
func (q *QuoteAcceptMsgData) decodeRecords() []tlv.Record { | ||
return []tlv.Record{ | ||
QuoteAcceptIDRecord(&q.ID), | ||
QuoteAcceptAssetIDRecord(&q.AssetID), | ||
QuoteAcceptGroupKeyRecord(&q.AssetGroupKey), | ||
QuoteAcceptAssetAmountRecord(&q.AssetAmount), | ||
QuoteAcceptAmtCharacteristicRecord(&q.SuggestedRateTick), | ||
QuoteAcceptMsgDataIDRecord(&q.ID), | ||
QuoteAcceptMsgDataCharacteristicRecord(&q.AmtCharacteristic), | ||
QuoteAcceptMsgDataExpiryRecord(&q.ExpirySeconds), | ||
QuoteAcceptMsgDataSig(&q.Sig), | ||
} | ||
} | ||
|
||
// Decode decodes the structure from a TLV stream. | ||
func (q *QuoteAccept) Decode(r io.Reader) error { | ||
stream, err := tlv.NewStream(q.DecodeRecords()...) | ||
func (q *QuoteAcceptMsgData) Decode(r io.Reader) error { | ||
stream, err := tlv.NewStream(q.decodeRecords()...) | ||
if err != nil { | ||
return err | ||
} | ||
return stream.Decode(r) | ||
} | ||
|
||
//func EncodeAsPeerMsg() | ||
// QuoteAccept is a struct that represents an accepted quote message. | ||
type QuoteAccept struct { | ||
// Peer is the peer that sent the quote request. | ||
Peer route.Vertex | ||
|
||
// QuoteAcceptMsgData is the message data from the quote accept message. | ||
QuoteAcceptMsgData | ||
} | ||
|
||
// LndCustomMsg returns a custom message that can be sent to a peer using the | ||
// lndclient. | ||
func (q *QuoteAccept) LndCustomMsg() (*lndclient.CustomMessage, error) { | ||
// Encode message data component as TLV bytes. | ||
var buff *bytes.Buffer | ||
err := q.QuoteAcceptMsgData.Encode(buff) | ||
if err != nil { | ||
return nil, fmt.Errorf("unable to encode quote accept "+ | ||
"message data: %w", err) | ||
} | ||
quoteAcceptBytes := buff.Bytes() | ||
|
||
return &lndclient.CustomMessage{ | ||
Peer: q.Peer, | ||
MsgType: MsgTypeQuoteAccept, | ||
Data: quoteAcceptBytes, | ||
}, nil | ||
} |
Oops, something went wrong.