diff --git a/funding/manager.go b/funding/manager.go index c0cd1fb..393318d 100644 --- a/funding/manager.go +++ b/funding/manager.go @@ -996,7 +996,7 @@ func (m *Manager) RemovePendingBatchArtifacts( // ticket. The offer is signed with the local lnd's node public key. func (m *Manager) OfferSidecar(ctx context.Context, capacity, pushAmt btcutil.Amount, duration uint32, - acctPubKey *keychain.KeyDescriptor) (*sidecar.Ticket, error) { + acctPubKey *keychain.KeyDescriptor, auto bool) (*sidecar.Ticket, error) { // Make sure the capacity and push amounts are sane. err := sidecar.CheckOfferParams(capacity, pushAmt, order.BaseSupplyUnit) @@ -1008,7 +1008,7 @@ func (m *Manager) OfferSidecar(ctx context.Context, capacity, // now. ticket, err := sidecar.NewTicket( sidecar.VersionDefault, capacity, pushAmt, duration, - acctPubKey.PubKey, + acctPubKey.PubKey, auto, ) if err != nil { return nil, fmt.Errorf("error creating sidecar ticket: %v", err) diff --git a/funding/manager_test.go b/funding/manager_test.go index a382e08..32e7c62 100644 --- a/funding/manager_test.go +++ b/funding/manager_test.go @@ -619,7 +619,7 @@ func TestDeriveFundingShim(t *testing.T) { // And the second test is with a sidecar channel bid. ticket, err := sidecar.NewTicket( - sidecar.VersionDefault, 400_000, 0, 12345, pubKeyBid, + sidecar.VersionDefault, 400_000, 0, 12345, pubKeyBid, false, ) require.NoError(t, err) ticket.Recipient = &sidecar.Recipient{ @@ -823,7 +823,7 @@ func TestOfferSidecarValidation(t *testing.T) { for _, testCase := range negativeCases { _, err := h.mgr.OfferSidecar( context.Background(), testCase.capacity, - testCase.pushAmt, 2016, + testCase.pushAmt, 2016, nil, nil, false, ) require.Error(t, err) require.Contains(t, err.Error(), testCase.expectedErr) @@ -855,6 +855,9 @@ func TestOfferSidecar(t *testing.T) { capacity, pushAmt := btcutil.Amount(100_000), btcutil.Amount(40_000) ticket, err := h.mgr.OfferSidecar( context.Background(), capacity, pushAmt, 2016, + &keychain.KeyDescriptor{ + PubKey: privKey.PubKey(), + }, nil, false, ) require.NoError(t, err) diff --git a/order/batch_test.go b/order/batch_test.go index 2da8950..8fded5c 100644 --- a/order/batch_test.go +++ b/order/batch_test.go @@ -98,7 +98,7 @@ func TestChannelOutput(t *testing.T) { // And the second test is with a sidecar channel bid. ticket, err := sidecar.NewTicket( - sidecar.VersionDefault, 400_000, 0, 12345, pubKeyBid, + sidecar.VersionDefault, 400_000, 0, 12345, pubKeyBid, false, ) require.NoError(t, err) ticket.Recipient = &sidecar.Recipient{ diff --git a/rpcserver.go b/rpcserver.go index b524c7f..8d7c7dd 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2230,6 +2230,7 @@ func (s *rpcServer) OfferSidecar(ctx context.Context, ctx, btcutil.Amount(req.Bid.Details.Amt), btcutil.Amount(req.Bid.SelfChanBalance), req.Bid.LeaseDurationBlocks, acct.TraderKey, + req.AutoNegotiate, ) if err != nil { return nil, err diff --git a/sidecar/interface.go b/sidecar/interface.go index 07ed241..2bdd333 100644 --- a/sidecar/interface.go +++ b/sidecar/interface.go @@ -114,6 +114,10 @@ type Offer struct { // SigOfferDigest is a signature over the offer digest, signed with the // private key that corresponds to the SignPubKey above. SigOfferDigest *btcec.Signature + + // Auto determines if the provider requires that the ticket be + // completed using an automated negotiation sequence. + Auto bool } // Recipient is a struct holding the information about the recipient of the @@ -196,7 +200,8 @@ type Ticket struct { // NewTicket creates a new sidecar ticket with the given version and offer // information. func NewTicket(version Version, capacity, pushAmt btcutil.Amount, - duration uint32, offerPubKey *btcec.PublicKey) (*Ticket, error) { + duration uint32, offerPubKey *btcec.PublicKey, + auto bool) (*Ticket, error) { t := &Ticket{ Version: version, @@ -206,6 +211,7 @@ func NewTicket(version Version, capacity, pushAmt btcutil.Amount, PushAmt: pushAmt, LeaseDurationBlocks: duration, SignPubKey: offerPubKey, + Auto: auto, }, } @@ -226,7 +232,7 @@ func (t *Ticket) OfferDigest() ([32]byte, error) { case VersionDefault: err := lnwire.WriteElements( &msg, t.ID[:], uint8(t.Version), t.Offer.Capacity, - t.Offer.PushAmt, + t.Offer.PushAmt, t.Offer.Auto, ) if err != nil { return result, err diff --git a/sidecar/tlv.go b/sidecar/tlv.go index 2724e79..f1669be 100644 --- a/sidecar/tlv.go +++ b/sidecar/tlv.go @@ -22,6 +22,7 @@ const ( leaseDurationType tlv.Type = 13 signPubKeyType tlv.Type = 14 sigOfferDigestType tlv.Type = 15 + offerAutoType tlv.Type = 16 recipientType tlv.Type = 20 nodePubKeyType tlv.Type = 21 @@ -176,12 +177,18 @@ func serializeOffer(o Offer) ([]byte, error) { capacity := uint64(o.Capacity) pushAmt := uint64(o.PushAmt) + var autoAsInt uint8 + if o.Auto { + autoAsInt = 1 + } + tlvRecords := []tlv.Record{ tlv.MakePrimitiveRecord(capacityType, &capacity), tlv.MakePrimitiveRecord(pushAmtType, &pushAmt), tlv.MakePrimitiveRecord( leaseDurationType, &o.LeaseDurationBlocks, ), + tlv.MakePrimitiveRecord(offerAutoType, &autoAsInt), } if o.SignPubKey != nil { @@ -205,6 +212,7 @@ func deserializeOffer(offerBytes []byte) (Offer, error) { var ( o = Offer{} capacity, pushAmt uint64 + autoAsInt uint8 ) if err := decodeBytes( @@ -218,10 +226,12 @@ func deserializeOffer(offerBytes []byte) (Offer, error) { tlv.MakeStaticRecord( sigOfferDigestType, &o.SigOfferDigest, 64, ESig, DSig, ), + tlv.MakePrimitiveRecord(offerAutoType, &autoAsInt), ); err != nil { return o, err } + o.Auto = autoAsInt == 1 o.Capacity = btcutil.Amount(capacity) o.PushAmt = btcutil.Amount(pushAmt) @@ -376,6 +386,8 @@ func DBytes8(r io.Reader, val interface{}, _ *[8]byte, l uint64) error { // encodeBytes encodes the given tlv records into a byte slice. func encodeBytes(tlvRecords ...tlv.Record) ([]byte, error) { + tlv.SortRecords(tlvRecords) + tlvStream, err := tlv.NewStream(tlvRecords...) if err != nil { return nil, err @@ -392,6 +404,8 @@ func encodeBytes(tlvRecords ...tlv.Record) ([]byte, error) { // decodeBytes decodes the given byte slice interpreting the data as a tlv // stream containing the given records. func decodeBytes(tlvBytes []byte, tlvRecords ...tlv.Record) error { + tlv.SortRecords(tlvRecords) + tlvStream, err := tlv.NewStream(tlvRecords...) if err != nil { return err diff --git a/sidecar/tlv_test.go b/sidecar/tlv_test.go index 23e6f93..e84473e 100644 --- a/sidecar/tlv_test.go +++ b/sidecar/tlv_test.go @@ -77,6 +77,7 @@ func TestSerializeTicket(t *testing.T) { R: new(big.Int).SetInt64(22), S: new(big.Int).SetInt64(55), }, + Auto: true, }, Recipient: &Recipient{ NodePubKey: testPubKey, diff --git a/sidecar/verification_test.go b/sidecar/verification_test.go index 70bd036..5efbc0e 100644 --- a/sidecar/verification_test.go +++ b/sidecar/verification_test.go @@ -146,6 +146,7 @@ func TestVerifyOffer(t *testing.T) { Offer: Offer{ SignPubKey: providerPubKey, SigOfferDigest: testOfferSig, + Auto: true, }, }, expectedErr: "",