package models import ( "encoding/binary" "fmt" "io" "github.com/lightningnetwork/lnd/lnwire" ) const ( // serializedCircuitKeyLen is the exact length needed to encode a // serialized CircuitKey. serializedCircuitKeyLen = 16 ) var ( // ErrInvalidCircuitKeyLen signals that a circuit key could not be // decoded because the byte slice is of an invalid length. ErrInvalidCircuitKeyLen = fmt.Errorf("length of serialized circuit " + "key must be 16 bytes") ) // CircuitKey is used by a channel to uniquely identify the HTLCs it receives // from the switch, and is used to purge our in-memory state of HTLCs that have // already been processed by a link. Two list of CircuitKeys are included in // each CommitDiff to allow a link to determine which in-memory htlcs directed // the opening and closing of circuits in the switch's circuit map. type CircuitKey struct { // ChanID is the short chanid indicating the HTLC's origin. // // NOTE: It is fine for this value to be blank, as this indicates a // locally-sourced payment. ChanID lnwire.ShortChannelID // HtlcID is the unique htlc index predominately assigned by links, // though can also be assigned by switch in the case of locally-sourced // payments. HtlcID uint64 } // SetBytes deserializes the given bytes into this CircuitKey. func (k *CircuitKey) SetBytes(bs []byte) error { if len(bs) != serializedCircuitKeyLen { return ErrInvalidCircuitKeyLen } k.ChanID = lnwire.NewShortChanIDFromInt( binary.BigEndian.Uint64(bs[:8])) k.HtlcID = binary.BigEndian.Uint64(bs[8:]) return nil } // Bytes returns the serialized bytes for this circuit key. func (k CircuitKey) Bytes() []byte { bs := make([]byte, serializedCircuitKeyLen) binary.BigEndian.PutUint64(bs[:8], k.ChanID.ToUint64()) binary.BigEndian.PutUint64(bs[8:], k.HtlcID) return bs } // Encode writes a CircuitKey to the provided io.Writer. func (k *CircuitKey) Encode(w io.Writer) error { var scratch [serializedCircuitKeyLen]byte binary.BigEndian.PutUint64(scratch[:8], k.ChanID.ToUint64()) binary.BigEndian.PutUint64(scratch[8:], k.HtlcID) _, err := w.Write(scratch[:]) return err } // Decode reads a CircuitKey from the provided io.Reader. func (k *CircuitKey) Decode(r io.Reader) error { var scratch [serializedCircuitKeyLen]byte if _, err := io.ReadFull(r, scratch[:]); err != nil { return err } k.ChanID = lnwire.NewShortChanIDFromInt( binary.BigEndian.Uint64(scratch[:8])) k.HtlcID = binary.BigEndian.Uint64(scratch[8:]) return nil } // String returns a string representation of the CircuitKey. func (k CircuitKey) String() string { return fmt.Sprintf("(Chan ID=%s, HTLC ID=%d)", k.ChanID, k.HtlcID) } // ForwardingPolicy describes the set of constraints that a given ChannelLink // is to adhere to when forwarding HTLC's. For each incoming HTLC, this set of // constraints will be consulted in order to ensure that adequate fees are // paid, and our time-lock parameters are respected. In the event that an // incoming HTLC violates any of these constraints, it is to be _rejected_ with // the error possibly carrying along a ChannelUpdate message that includes the // latest policy. type ForwardingPolicy struct { // MinHTLCOut is the smallest HTLC that is to be forwarded. MinHTLCOut lnwire.MilliSatoshi // MaxHTLC is the largest HTLC that is to be forwarded. MaxHTLC lnwire.MilliSatoshi // BaseFee is the base fee, expressed in milli-satoshi that must be // paid for each incoming HTLC. This field, combined with FeeRate is // used to compute the required fee for a given HTLC. BaseFee lnwire.MilliSatoshi // FeeRate is the fee rate, expressed in milli-satoshi that must be // paid for each incoming HTLC. This field combined with BaseFee is // used to compute the required fee for a given HTLC. FeeRate lnwire.MilliSatoshi // InboundFee is the fee that must be paid for incoming HTLCs. InboundFee InboundFee // TimeLockDelta is the absolute time-lock value, expressed in blocks, // that will be subtracted from an incoming HTLC's timelock value to // create the time-lock value for the forwarded outgoing HTLC. The // following constraint MUST hold for an HTLC to be forwarded: // // * incomingHtlc.timeLock - timeLockDelta = fwdInfo.OutgoingCTLV // // where fwdInfo is the forwarding information extracted from the // per-hop payload of the incoming HTLC's onion packet. TimeLockDelta uint32 // TODO(roasbeef): add fee module inside of switch }