mirror of
https://github.com/muun/recovery.git
synced 2025-11-11 06:20:16 -05:00
Release v0.1.0
This commit is contained in:
19
vendor/github.com/lightningnetwork/lnd/LICENSE
generated
vendored
Normal file
19
vendor/github.com/lightningnetwork/lnd/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (C) 2015-2018 Lightning Labs and The Lightning Network Developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
18
vendor/github.com/lightningnetwork/lnd/lnwire/README.md
generated
vendored
Normal file
18
vendor/github.com/lightningnetwork/lnd/lnwire/README.md
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
lnwire
|
||||
======
|
||||
|
||||
[](https://travis-ci.org/lightningnetwork/lnd)
|
||||
[](https://github.com/lightningnetwork/lnd/blob/master/LICENSE)
|
||||
[](http://godoc.org/github.com/lightningnetwork/lnd/lnwire)
|
||||
|
||||
The lnwire package implements the Lightning Network wire protocol.
|
||||
|
||||
This package has intentionally been designed so it can be used as a standalone
|
||||
package for any projects needing to interface with lightning peers at the wire
|
||||
protocol level.
|
||||
|
||||
## Installation and Updating
|
||||
|
||||
```bash
|
||||
$ go get -u github.com/lightningnetwork/lnd/lnwire
|
||||
```
|
||||
158
vendor/github.com/lightningnetwork/lnd/lnwire/accept_channel.go
generated
vendored
Normal file
158
vendor/github.com/lightningnetwork/lnd/lnwire/accept_channel.go
generated
vendored
Normal file
@@ -0,0 +1,158 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/btcsuite/btcutil"
|
||||
)
|
||||
|
||||
// AcceptChannel is the message Bob sends to Alice after she initiates the
|
||||
// single funder channel workflow via an AcceptChannel message. Once Alice
|
||||
// receives Bob's response, then she has all the items necessary to construct
|
||||
// the funding transaction, and both commitment transactions.
|
||||
type AcceptChannel struct {
|
||||
// PendingChannelID serves to uniquely identify the future channel
|
||||
// created by the initiated single funder workflow.
|
||||
PendingChannelID [32]byte
|
||||
|
||||
// DustLimit is the specific dust limit the sender of this message
|
||||
// would like enforced on their version of the commitment transaction.
|
||||
// Any output below this value will be "trimmed" from the commitment
|
||||
// transaction, with the amount of the HTLC going to dust.
|
||||
DustLimit btcutil.Amount
|
||||
|
||||
// MaxValueInFlight represents the maximum amount of coins that can be
|
||||
// pending within the channel at any given time. If the amount of funds
|
||||
// in limbo exceeds this amount, then the channel will be failed.
|
||||
MaxValueInFlight MilliSatoshi
|
||||
|
||||
// ChannelReserve is the amount of BTC that the receiving party MUST
|
||||
// maintain a balance above at all times. This is a safety mechanism to
|
||||
// ensure that both sides always have skin in the game during the
|
||||
// channel's lifetime.
|
||||
ChannelReserve btcutil.Amount
|
||||
|
||||
// HtlcMinimum is the smallest HTLC that the sender of this message
|
||||
// will accept.
|
||||
HtlcMinimum MilliSatoshi
|
||||
|
||||
// MinAcceptDepth is the minimum depth that the initiator of the
|
||||
// channel should wait before considering the channel open.
|
||||
MinAcceptDepth uint32
|
||||
|
||||
// CsvDelay is the number of blocks to use for the relative time lock
|
||||
// in the pay-to-self output of both commitment transactions.
|
||||
CsvDelay uint16
|
||||
|
||||
// MaxAcceptedHTLCs is the total number of incoming HTLC's that the
|
||||
// sender of this channel will accept.
|
||||
//
|
||||
// TODO(roasbeef): acks the initiator's, same with max in flight?
|
||||
MaxAcceptedHTLCs uint16
|
||||
|
||||
// FundingKey is the key that should be used on behalf of the sender
|
||||
// within the 2-of-2 multi-sig output that it contained within the
|
||||
// funding transaction.
|
||||
FundingKey *btcec.PublicKey
|
||||
|
||||
// RevocationPoint is the base revocation point for the sending party.
|
||||
// Any commitment transaction belonging to the receiver of this message
|
||||
// should use this key and their per-commitment point to derive the
|
||||
// revocation key for the commitment transaction.
|
||||
RevocationPoint *btcec.PublicKey
|
||||
|
||||
// PaymentPoint is the base payment point for the sending party. This
|
||||
// key should be combined with the per commitment point for a
|
||||
// particular commitment state in order to create the key that should
|
||||
// be used in any output that pays directly to the sending party, and
|
||||
// also within the HTLC covenant transactions.
|
||||
PaymentPoint *btcec.PublicKey
|
||||
|
||||
// DelayedPaymentPoint is the delay point for the sending party. This
|
||||
// key should be combined with the per commitment point to derive the
|
||||
// keys that are used in outputs of the sender's commitment transaction
|
||||
// where they claim funds.
|
||||
DelayedPaymentPoint *btcec.PublicKey
|
||||
|
||||
// HtlcPoint is the base point used to derive the set of keys for this
|
||||
// party that will be used within the HTLC public key scripts. This
|
||||
// value is combined with the receiver's revocation base point in order
|
||||
// to derive the keys that are used within HTLC scripts.
|
||||
HtlcPoint *btcec.PublicKey
|
||||
|
||||
// FirstCommitmentPoint is the first commitment point for the sending
|
||||
// party. This value should be combined with the receiver's revocation
|
||||
// base point in order to derive the revocation keys that are placed
|
||||
// within the commitment transaction of the sender.
|
||||
FirstCommitmentPoint *btcec.PublicKey
|
||||
}
|
||||
|
||||
// A compile time check to ensure AcceptChannel implements the lnwire.Message
|
||||
// interface.
|
||||
var _ Message = (*AcceptChannel)(nil)
|
||||
|
||||
// Encode serializes the target AcceptChannel into the passed io.Writer
|
||||
// implementation. Serialization will observe the rules defined by the passed
|
||||
// protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *AcceptChannel) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
a.PendingChannelID[:],
|
||||
a.DustLimit,
|
||||
a.MaxValueInFlight,
|
||||
a.ChannelReserve,
|
||||
a.HtlcMinimum,
|
||||
a.MinAcceptDepth,
|
||||
a.CsvDelay,
|
||||
a.MaxAcceptedHTLCs,
|
||||
a.FundingKey,
|
||||
a.RevocationPoint,
|
||||
a.PaymentPoint,
|
||||
a.DelayedPaymentPoint,
|
||||
a.HtlcPoint,
|
||||
a.FirstCommitmentPoint,
|
||||
)
|
||||
}
|
||||
|
||||
// Decode deserializes the serialized AcceptChannel stored in the passed
|
||||
// io.Reader into the target AcceptChannel using the deserialization rules
|
||||
// defined by the passed protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *AcceptChannel) Decode(r io.Reader, pver uint32) error {
|
||||
return ReadElements(r,
|
||||
a.PendingChannelID[:],
|
||||
&a.DustLimit,
|
||||
&a.MaxValueInFlight,
|
||||
&a.ChannelReserve,
|
||||
&a.HtlcMinimum,
|
||||
&a.MinAcceptDepth,
|
||||
&a.CsvDelay,
|
||||
&a.MaxAcceptedHTLCs,
|
||||
&a.FundingKey,
|
||||
&a.RevocationPoint,
|
||||
&a.PaymentPoint,
|
||||
&a.DelayedPaymentPoint,
|
||||
&a.HtlcPoint,
|
||||
&a.FirstCommitmentPoint,
|
||||
)
|
||||
}
|
||||
|
||||
// MsgType returns the MessageType code which uniquely identifies this message
|
||||
// as an AcceptChannel on the wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *AcceptChannel) MsgType() MessageType {
|
||||
return MsgAcceptChannel
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload length for a
|
||||
// AcceptChannel message.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *AcceptChannel) MaxPayloadLength(uint32) uint32 {
|
||||
// 32 + (8 * 4) + (4 * 1) + (2 * 2) + (33 * 6)
|
||||
return 270
|
||||
}
|
||||
108
vendor/github.com/lightningnetwork/lnd/lnwire/announcement_signatures.go
generated
vendored
Normal file
108
vendor/github.com/lightningnetwork/lnd/lnwire/announcement_signatures.go
generated
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"io"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
// AnnounceSignatures this is a direct message between two endpoints of a
|
||||
// channel and serves as an opt-in mechanism to allow the announcement of
|
||||
// the channel to the rest of the network. It contains the necessary
|
||||
// signatures by the sender to construct the channel announcement message.
|
||||
type AnnounceSignatures struct {
|
||||
// ChannelID is the unique description of the funding transaction.
|
||||
// Channel id is better for users and debugging and short channel id is
|
||||
// used for quick test on existence of the particular utxo inside the
|
||||
// block chain, because it contains information about block.
|
||||
ChannelID ChannelID
|
||||
|
||||
// ShortChannelID is the unique description of the funding
|
||||
// transaction. It is constructed with the most significant 3 bytes
|
||||
// as the block height, the next 3 bytes indicating the transaction
|
||||
// index within the block, and the least significant two bytes
|
||||
// indicating the output index which pays to the channel.
|
||||
ShortChannelID ShortChannelID
|
||||
|
||||
// NodeSignature is the signature which contains the signed announce
|
||||
// channel message, by this signature we proof that we possess of the
|
||||
// node pub key and creating the reference node_key -> bitcoin_key.
|
||||
NodeSignature Sig
|
||||
|
||||
// BitcoinSignature is the signature which contains the signed node
|
||||
// public key, by this signature we proof that we possess of the
|
||||
// bitcoin key and and creating the reverse reference bitcoin_key ->
|
||||
// node_key.
|
||||
BitcoinSignature Sig
|
||||
|
||||
// ExtraOpaqueData is the set of data that was appended to this
|
||||
// message, some of which we may not actually know how to iterate or
|
||||
// parse. By holding onto this data, we ensure that we're able to
|
||||
// properly validate the set of signatures that cover these new fields,
|
||||
// and ensure we're able to make upgrades to the network in a forwards
|
||||
// compatible manner.
|
||||
ExtraOpaqueData []byte
|
||||
}
|
||||
|
||||
// A compile time check to ensure AnnounceSignatures implements the
|
||||
// lnwire.Message interface.
|
||||
var _ Message = (*AnnounceSignatures)(nil)
|
||||
|
||||
// Decode deserializes a serialized AnnounceSignatures stored in the passed
|
||||
// io.Reader observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *AnnounceSignatures) Decode(r io.Reader, pver uint32) error {
|
||||
err := ReadElements(r,
|
||||
&a.ChannelID,
|
||||
&a.ShortChannelID,
|
||||
&a.NodeSignature,
|
||||
&a.BitcoinSignature,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Now that we've read out all the fields that we explicitly know of,
|
||||
// we'll collect the remainder into the ExtraOpaqueData field. If there
|
||||
// aren't any bytes, then we'll snip off the slice to avoid carrying
|
||||
// around excess capacity.
|
||||
a.ExtraOpaqueData, err = ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(a.ExtraOpaqueData) == 0 {
|
||||
a.ExtraOpaqueData = nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Encode serializes the target AnnounceSignatures into the passed io.Writer
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *AnnounceSignatures) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
a.ChannelID,
|
||||
a.ShortChannelID,
|
||||
a.NodeSignature,
|
||||
a.BitcoinSignature,
|
||||
a.ExtraOpaqueData,
|
||||
)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
// wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *AnnounceSignatures) MsgType() MessageType {
|
||||
return MsgAnnounceSignatures
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload size for this message
|
||||
// observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *AnnounceSignatures) MaxPayloadLength(pver uint32) uint32 {
|
||||
return 65533
|
||||
}
|
||||
160
vendor/github.com/lightningnetwork/lnd/lnwire/channel_announcement.go
generated
vendored
Normal file
160
vendor/github.com/lightningnetwork/lnd/lnwire/channel_announcement.go
generated
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
)
|
||||
|
||||
// ChannelAnnouncement message is used to announce the existence of a channel
|
||||
// between two peers in the overlay, which is propagated by the discovery
|
||||
// service over broadcast handler.
|
||||
type ChannelAnnouncement struct {
|
||||
// This signatures are used by nodes in order to create cross
|
||||
// references between node's channel and node. Requiring both nodes
|
||||
// to sign indicates they are both willing to route other payments via
|
||||
// this node.
|
||||
NodeSig1 Sig
|
||||
NodeSig2 Sig
|
||||
|
||||
// This signatures are used by nodes in order to create cross
|
||||
// references between node's channel and node. Requiring the bitcoin
|
||||
// signatures proves they control the channel.
|
||||
BitcoinSig1 Sig
|
||||
BitcoinSig2 Sig
|
||||
|
||||
// Features is the feature vector that encodes the features supported
|
||||
// by the target node. This field can be used to signal the type of the
|
||||
// channel, or modifications to the fields that would normally follow
|
||||
// this vector.
|
||||
Features *RawFeatureVector
|
||||
|
||||
// ChainHash denotes the target chain that this channel was opened
|
||||
// within. This value should be the genesis hash of the target chain.
|
||||
ChainHash chainhash.Hash
|
||||
|
||||
// ShortChannelID is the unique description of the funding transaction,
|
||||
// or where exactly it's located within the target blockchain.
|
||||
ShortChannelID ShortChannelID
|
||||
|
||||
// The public keys of the two nodes who are operating the channel, such
|
||||
// that is NodeID1 the numerically-lesser than NodeID2 (ascending
|
||||
// numerical order).
|
||||
NodeID1 [33]byte
|
||||
NodeID2 [33]byte
|
||||
|
||||
// Public keys which corresponds to the keys which was declared in
|
||||
// multisig funding transaction output.
|
||||
BitcoinKey1 [33]byte
|
||||
BitcoinKey2 [33]byte
|
||||
|
||||
// ExtraOpaqueData is the set of data that was appended to this
|
||||
// message, some of which we may not actually know how to iterate or
|
||||
// parse. By holding onto this data, we ensure that we're able to
|
||||
// properly validate the set of signatures that cover these new fields,
|
||||
// and ensure we're able to make upgrades to the network in a forwards
|
||||
// compatible manner.
|
||||
ExtraOpaqueData []byte
|
||||
}
|
||||
|
||||
// A compile time check to ensure ChannelAnnouncement implements the
|
||||
// lnwire.Message interface.
|
||||
var _ Message = (*ChannelAnnouncement)(nil)
|
||||
|
||||
// Decode deserializes a serialized ChannelAnnouncement stored in the passed
|
||||
// io.Reader observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *ChannelAnnouncement) Decode(r io.Reader, pver uint32) error {
|
||||
err := ReadElements(r,
|
||||
&a.NodeSig1,
|
||||
&a.NodeSig2,
|
||||
&a.BitcoinSig1,
|
||||
&a.BitcoinSig2,
|
||||
&a.Features,
|
||||
a.ChainHash[:],
|
||||
&a.ShortChannelID,
|
||||
&a.NodeID1,
|
||||
&a.NodeID2,
|
||||
&a.BitcoinKey1,
|
||||
&a.BitcoinKey2,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Now that we've read out all the fields that we explicitly know of,
|
||||
// we'll collect the remainder into the ExtraOpaqueData field. If there
|
||||
// aren't any bytes, then we'll snip off the slice to avoid carrying
|
||||
// around excess capacity.
|
||||
a.ExtraOpaqueData, err = ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(a.ExtraOpaqueData) == 0 {
|
||||
a.ExtraOpaqueData = nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Encode serializes the target ChannelAnnouncement into the passed io.Writer
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *ChannelAnnouncement) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
a.NodeSig1,
|
||||
a.NodeSig2,
|
||||
a.BitcoinSig1,
|
||||
a.BitcoinSig2,
|
||||
a.Features,
|
||||
a.ChainHash[:],
|
||||
a.ShortChannelID,
|
||||
a.NodeID1,
|
||||
a.NodeID2,
|
||||
a.BitcoinKey1,
|
||||
a.BitcoinKey2,
|
||||
a.ExtraOpaqueData,
|
||||
)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
// wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *ChannelAnnouncement) MsgType() MessageType {
|
||||
return MsgChannelAnnouncement
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload size for this message
|
||||
// observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *ChannelAnnouncement) MaxPayloadLength(pver uint32) uint32 {
|
||||
return 65533
|
||||
}
|
||||
|
||||
// DataToSign is used to retrieve part of the announcement message which should
|
||||
// be signed.
|
||||
func (a *ChannelAnnouncement) DataToSign() ([]byte, error) {
|
||||
// We should not include the signatures itself.
|
||||
var w bytes.Buffer
|
||||
err := WriteElements(&w,
|
||||
a.Features,
|
||||
a.ChainHash[:],
|
||||
a.ShortChannelID,
|
||||
a.NodeID1,
|
||||
a.NodeID2,
|
||||
a.BitcoinKey1,
|
||||
a.BitcoinKey2,
|
||||
a.ExtraOpaqueData,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return w.Bytes(), nil
|
||||
}
|
||||
91
vendor/github.com/lightningnetwork/lnd/lnwire/channel_id.go
generated
vendored
Normal file
91
vendor/github.com/lightningnetwork/lnd/lnwire/channel_id.go
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"math"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
)
|
||||
|
||||
const (
|
||||
// MaxFundingTxOutputs is the maximum number of allowed outputs on a
|
||||
// funding transaction within the protocol. This is due to the fact
|
||||
// that we use 2-bytes to encode the index within the funding output
|
||||
// during the funding workflow. Funding transaction with more outputs
|
||||
// than this are considered invalid within the protocol.
|
||||
MaxFundingTxOutputs = math.MaxUint16
|
||||
)
|
||||
|
||||
// ChannelID is a series of 32-bytes that uniquely identifies all channels
|
||||
// within the network. The ChannelID is computed using the outpoint of the
|
||||
// funding transaction (the txid, and output index). Given a funding output the
|
||||
// ChannelID can be calculated by XOR'ing the big-endian serialization of the
|
||||
// txid and the big-endian serialization of the output index, truncated to
|
||||
// 2 bytes.
|
||||
type ChannelID [32]byte
|
||||
|
||||
// ConnectionWideID is an all-zero ChannelID, which is used to represent a
|
||||
// message intended for all channels to specific peer.
|
||||
var ConnectionWideID = ChannelID{}
|
||||
|
||||
// String returns the string representation of the ChannelID. This is just the
|
||||
// hex string encoding of the ChannelID itself.
|
||||
func (c ChannelID) String() string {
|
||||
return hex.EncodeToString(c[:])
|
||||
}
|
||||
|
||||
// NewChanIDFromOutPoint converts a target OutPoint into a ChannelID that is
|
||||
// usable within the network. In order to convert the OutPoint into a ChannelID,
|
||||
// we XOR the lower 2-bytes of the txid within the OutPoint with the big-endian
|
||||
// serialization of the Index of the OutPoint, truncated to 2-bytes.
|
||||
func NewChanIDFromOutPoint(op *wire.OutPoint) ChannelID {
|
||||
// First we'll copy the txid of the outpoint into our channel ID slice.
|
||||
var cid ChannelID
|
||||
copy(cid[:], op.Hash[:])
|
||||
|
||||
// With the txid copied over, we'll now XOR the lower 2-bytes of the
|
||||
// partial channelID with big-endian serialization of output index.
|
||||
xorTxid(&cid, uint16(op.Index))
|
||||
|
||||
return cid
|
||||
}
|
||||
|
||||
// xorTxid performs the transformation needed to transform an OutPoint into a
|
||||
// ChannelID. To do this, we expect the cid parameter to contain the txid
|
||||
// unaltered and the outputIndex to be the output index
|
||||
func xorTxid(cid *ChannelID, outputIndex uint16) {
|
||||
var buf [32]byte
|
||||
binary.BigEndian.PutUint16(buf[30:], outputIndex)
|
||||
|
||||
cid[30] = cid[30] ^ buf[30]
|
||||
cid[31] = cid[31] ^ buf[31]
|
||||
}
|
||||
|
||||
// GenPossibleOutPoints generates all the possible outputs given a channel ID.
|
||||
// In order to generate these possible outpoints, we perform a brute-force
|
||||
// search through the candidate output index space, performing a reverse
|
||||
// mapping from channelID back to OutPoint.
|
||||
func (c *ChannelID) GenPossibleOutPoints() [MaxFundingTxOutputs]wire.OutPoint {
|
||||
var possiblePoints [MaxFundingTxOutputs]wire.OutPoint
|
||||
for i := uint32(0); i < MaxFundingTxOutputs; i++ {
|
||||
cidCopy := *c
|
||||
xorTxid(&cidCopy, uint16(i))
|
||||
|
||||
possiblePoints[i] = wire.OutPoint{
|
||||
Hash: chainhash.Hash(cidCopy),
|
||||
Index: i,
|
||||
}
|
||||
}
|
||||
|
||||
return possiblePoints
|
||||
}
|
||||
|
||||
// IsChanPoint returns true if the OutPoint passed corresponds to the target
|
||||
// ChannelID.
|
||||
func (c ChannelID) IsChanPoint(op *wire.OutPoint) bool {
|
||||
candidateCid := NewChanIDFromOutPoint(op)
|
||||
|
||||
return candidateCid == c
|
||||
}
|
||||
166
vendor/github.com/lightningnetwork/lnd/lnwire/channel_reestablish.go
generated
vendored
Normal file
166
vendor/github.com/lightningnetwork/lnd/lnwire/channel_reestablish.go
generated
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
)
|
||||
|
||||
// ChannelReestablish is a message sent between peers that have an existing
|
||||
// open channel upon connection reestablishment. This message allows both sides
|
||||
// to report their local state, and their current knowledge of the state of the
|
||||
// remote commitment chain. If a deviation is detected and can be recovered
|
||||
// from, then the necessary messages will be retransmitted. If the level of
|
||||
// desynchronization if irreconcilable, then the channel will be force closed.
|
||||
type ChannelReestablish struct {
|
||||
// ChanID is the channel ID of the channel state we're attempting
|
||||
// synchronize with the remote party.
|
||||
ChanID ChannelID
|
||||
|
||||
// NextLocalCommitHeight is the next local commitment height of the
|
||||
// sending party. If the height of the sender's commitment chain from
|
||||
// the receiver's Pov is one less that this number, then the sender
|
||||
// should re-send the *exact* same proposed commitment.
|
||||
//
|
||||
// In other words, the receiver should re-send their last sent
|
||||
// commitment iff:
|
||||
//
|
||||
// * NextLocalCommitHeight == remoteCommitChain.Height
|
||||
//
|
||||
// This covers the case of a lost commitment which was sent by the
|
||||
// sender of this message, but never received by the receiver of this
|
||||
// message.
|
||||
NextLocalCommitHeight uint64
|
||||
|
||||
// RemoteCommitTailHeight is the height of the receiving party's
|
||||
// unrevoked commitment from the PoV of the sender of this message. If
|
||||
// the height of the receiver's commitment is *one more* than this
|
||||
// value, then their prior RevokeAndAck message should be
|
||||
// retransmitted.
|
||||
//
|
||||
// In other words, the receiver should re-send their last sent
|
||||
// RevokeAndAck message iff:
|
||||
//
|
||||
// * localCommitChain.tail().Height == RemoteCommitTailHeight + 1
|
||||
//
|
||||
// This covers the case of a lost revocation, wherein the receiver of
|
||||
// the message sent a revocation for a prior state, but the sender of
|
||||
// the message never fully processed it.
|
||||
RemoteCommitTailHeight uint64
|
||||
|
||||
// LastRemoteCommitSecret is the last commitment secret that the
|
||||
// receiving node has sent to the sending party. This will be the
|
||||
// secret of the last revoked commitment transaction. Including this
|
||||
// provides proof that the sending node at least knows of this state,
|
||||
// as they couldn't have produced it if it wasn't sent, as the value
|
||||
// can be authenticated by querying the shachain or the receiving
|
||||
// party.
|
||||
LastRemoteCommitSecret [32]byte
|
||||
|
||||
// LocalUnrevokedCommitPoint is the commitment point used in the
|
||||
// current un-revoked commitment transaction of the sending party.
|
||||
LocalUnrevokedCommitPoint *btcec.PublicKey
|
||||
}
|
||||
|
||||
// A compile time check to ensure ChannelReestablish implements the
|
||||
// lnwire.Message interface.
|
||||
var _ Message = (*ChannelReestablish)(nil)
|
||||
|
||||
// Encode serializes the target ChannelReestablish into the passed io.Writer
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *ChannelReestablish) Encode(w io.Writer, pver uint32) error {
|
||||
err := WriteElements(w,
|
||||
a.ChanID,
|
||||
a.NextLocalCommitHeight,
|
||||
a.RemoteCommitTailHeight,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If the commit point wasn't sent, then we won't write out any of the
|
||||
// remaining fields as they're optional.
|
||||
if a.LocalUnrevokedCommitPoint == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Otherwise, we'll write out the remaining elements.
|
||||
return WriteElements(w, a.LastRemoteCommitSecret[:],
|
||||
a.LocalUnrevokedCommitPoint)
|
||||
}
|
||||
|
||||
// Decode deserializes a serialized ChannelReestablish stored in the passed
|
||||
// io.Reader observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *ChannelReestablish) Decode(r io.Reader, pver uint32) error {
|
||||
err := ReadElements(r,
|
||||
&a.ChanID,
|
||||
&a.NextLocalCommitHeight,
|
||||
&a.RemoteCommitTailHeight,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// This message has to currently defined optional fields. As a result,
|
||||
// we'll only proceed if there's still bytes remaining within the
|
||||
// reader.
|
||||
//
|
||||
// We'll manually parse out the optional fields in order to be able to
|
||||
// still utilize the io.Reader interface.
|
||||
|
||||
// We'll first attempt to read the optional commit secret, if we're at
|
||||
// the EOF, then this means the field wasn't included so we can exit
|
||||
// early.
|
||||
var buf [32]byte
|
||||
_, err = io.ReadFull(r, buf[:32])
|
||||
if err == io.EOF {
|
||||
return nil
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If the field is present, then we'll copy it over and proceed.
|
||||
copy(a.LastRemoteCommitSecret[:], buf[:])
|
||||
|
||||
// We'll conclude by parsing out the commitment point. We don't check
|
||||
// the error in this case, as it hey included the commit secret, then
|
||||
// they MUST also include the commit point.
|
||||
return ReadElement(r, &a.LocalUnrevokedCommitPoint)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
// wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *ChannelReestablish) MsgType() MessageType {
|
||||
return MsgChannelReestablish
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload size for this message
|
||||
// observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *ChannelReestablish) MaxPayloadLength(pver uint32) uint32 {
|
||||
var length uint32
|
||||
|
||||
// ChanID - 32 bytes
|
||||
length += 32
|
||||
|
||||
// NextLocalCommitHeight - 8 bytes
|
||||
length += 8
|
||||
|
||||
// RemoteCommitTailHeight - 8 bytes
|
||||
length += 8
|
||||
|
||||
// LastRemoteCommitSecret - 32 bytes
|
||||
length += 32
|
||||
|
||||
// LocalUnrevokedCommitPoint - 33 bytes
|
||||
length += 33
|
||||
|
||||
return length
|
||||
}
|
||||
253
vendor/github.com/lightningnetwork/lnd/lnwire/channel_update.go
generated
vendored
Normal file
253
vendor/github.com/lightningnetwork/lnd/lnwire/channel_update.go
generated
vendored
Normal file
@@ -0,0 +1,253 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
)
|
||||
|
||||
// ChanUpdateMsgFlags is a bitfield that signals whether optional fields are
|
||||
// present in the ChannelUpdate.
|
||||
type ChanUpdateMsgFlags uint8
|
||||
|
||||
const (
|
||||
// ChanUpdateOptionMaxHtlc is a bit that indicates whether the
|
||||
// optional htlc_maximum_msat field is present in this ChannelUpdate.
|
||||
ChanUpdateOptionMaxHtlc ChanUpdateMsgFlags = 1 << iota
|
||||
)
|
||||
|
||||
// String returns the bitfield flags as a string.
|
||||
func (c ChanUpdateMsgFlags) String() string {
|
||||
return fmt.Sprintf("%08b", c)
|
||||
}
|
||||
|
||||
// HasMaxHtlc returns true if the htlc_maximum_msat option bit is set in the
|
||||
// message flags.
|
||||
func (c ChanUpdateMsgFlags) HasMaxHtlc() bool {
|
||||
return c&ChanUpdateOptionMaxHtlc != 0
|
||||
}
|
||||
|
||||
// ChanUpdateChanFlags is a bitfield that signals various options concerning a
|
||||
// particular channel edge. Each bit is to be examined in order to determine
|
||||
// how the ChannelUpdate message is to be interpreted.
|
||||
type ChanUpdateChanFlags uint8
|
||||
|
||||
const (
|
||||
// ChanUpdateDirection indicates the direction of a channel update. If
|
||||
// this bit is set to 0 if Node1 (the node with the "smaller" Node ID)
|
||||
// is updating the channel, and to 1 otherwise.
|
||||
ChanUpdateDirection ChanUpdateChanFlags = 1 << iota
|
||||
|
||||
// ChanUpdateDisabled is a bit that indicates if the channel edge
|
||||
// selected by the ChanUpdateDirection bit is to be treated as being
|
||||
// disabled.
|
||||
ChanUpdateDisabled
|
||||
)
|
||||
|
||||
// String returns the bitfield flags as a string.
|
||||
func (c ChanUpdateChanFlags) String() string {
|
||||
return fmt.Sprintf("%08b", c)
|
||||
}
|
||||
|
||||
// ChannelUpdate message is used after channel has been initially announced.
|
||||
// Each side independently announces its fees and minimum expiry for HTLCs and
|
||||
// other parameters. Also this message is used to redeclare initially set
|
||||
// channel parameters.
|
||||
type ChannelUpdate struct {
|
||||
// Signature is used to validate the announced data and prove the
|
||||
// ownership of node id.
|
||||
Signature Sig
|
||||
|
||||
// ChainHash denotes the target chain that this channel was opened
|
||||
// within. This value should be the genesis hash of the target chain.
|
||||
// Along with the short channel ID, this uniquely identifies the
|
||||
// channel globally in a blockchain.
|
||||
ChainHash chainhash.Hash
|
||||
|
||||
// ShortChannelID is the unique description of the funding transaction.
|
||||
ShortChannelID ShortChannelID
|
||||
|
||||
// Timestamp allows ordering in the case of multiple announcements. We
|
||||
// should ignore the message if timestamp is not greater than
|
||||
// the last-received.
|
||||
Timestamp uint32
|
||||
|
||||
// MessageFlags is a bitfield that describes whether optional fields
|
||||
// are present in this update. Currently, the least-significant bit
|
||||
// must be set to 1 if the optional field MaxHtlc is present.
|
||||
MessageFlags ChanUpdateMsgFlags
|
||||
|
||||
// ChannelFlags is a bitfield that describes additional meta-data
|
||||
// concerning how the update is to be interpreted. Currently, the
|
||||
// least-significant bit must be set to 0 if the creating node
|
||||
// corresponds to the first node in the previously sent channel
|
||||
// announcement and 1 otherwise. If the second bit is set, then the
|
||||
// channel is set to be disabled.
|
||||
ChannelFlags ChanUpdateChanFlags
|
||||
|
||||
// TimeLockDelta is the minimum number of blocks this node requires to
|
||||
// be added to the expiry of HTLCs. This is a security parameter
|
||||
// determined by the node operator. This value represents the required
|
||||
// gap between the time locks of the incoming and outgoing HTLC's set
|
||||
// to this node.
|
||||
TimeLockDelta uint16
|
||||
|
||||
// HtlcMinimumMsat is the minimum HTLC value which will be accepted.
|
||||
HtlcMinimumMsat MilliSatoshi
|
||||
|
||||
// BaseFee is the base fee that must be used for incoming HTLC's to
|
||||
// this particular channel. This value will be tacked onto the required
|
||||
// for a payment independent of the size of the payment.
|
||||
BaseFee uint32
|
||||
|
||||
// FeeRate is the fee rate that will be charged per millionth of a
|
||||
// satoshi.
|
||||
FeeRate uint32
|
||||
|
||||
// HtlcMaximumMsat is the maximum HTLC value which will be accepted.
|
||||
HtlcMaximumMsat MilliSatoshi
|
||||
|
||||
// ExtraOpaqueData is the set of data that was appended to this
|
||||
// message, some of which we may not actually know how to iterate or
|
||||
// parse. By holding onto this data, we ensure that we're able to
|
||||
// properly validate the set of signatures that cover these new fields,
|
||||
// and ensure we're able to make upgrades to the network in a forwards
|
||||
// compatible manner.
|
||||
ExtraOpaqueData []byte
|
||||
}
|
||||
|
||||
// A compile time check to ensure ChannelUpdate implements the lnwire.Message
|
||||
// interface.
|
||||
var _ Message = (*ChannelUpdate)(nil)
|
||||
|
||||
// Decode deserializes a serialized ChannelUpdate stored in the passed
|
||||
// io.Reader observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *ChannelUpdate) Decode(r io.Reader, pver uint32) error {
|
||||
err := ReadElements(r,
|
||||
&a.Signature,
|
||||
a.ChainHash[:],
|
||||
&a.ShortChannelID,
|
||||
&a.Timestamp,
|
||||
&a.MessageFlags,
|
||||
&a.ChannelFlags,
|
||||
&a.TimeLockDelta,
|
||||
&a.HtlcMinimumMsat,
|
||||
&a.BaseFee,
|
||||
&a.FeeRate,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Now check whether the max HTLC field is present and read it if so.
|
||||
if a.MessageFlags.HasMaxHtlc() {
|
||||
if err := ReadElements(r, &a.HtlcMaximumMsat); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we've read out all the fields that we explicitly know of,
|
||||
// we'll collect the remainder into the ExtraOpaqueData field. If there
|
||||
// aren't any bytes, then we'll snip off the slice to avoid carrying
|
||||
// around excess capacity.
|
||||
a.ExtraOpaqueData, err = ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(a.ExtraOpaqueData) == 0 {
|
||||
a.ExtraOpaqueData = nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Encode serializes the target ChannelUpdate into the passed io.Writer
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *ChannelUpdate) Encode(w io.Writer, pver uint32) error {
|
||||
err := WriteElements(w,
|
||||
a.Signature,
|
||||
a.ChainHash[:],
|
||||
a.ShortChannelID,
|
||||
a.Timestamp,
|
||||
a.MessageFlags,
|
||||
a.ChannelFlags,
|
||||
a.TimeLockDelta,
|
||||
a.HtlcMinimumMsat,
|
||||
a.BaseFee,
|
||||
a.FeeRate,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Now append optional fields if they are set. Currently, the only
|
||||
// optional field is max HTLC.
|
||||
if a.MessageFlags.HasMaxHtlc() {
|
||||
if err := WriteElements(w, a.HtlcMaximumMsat); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, append any extra opaque data.
|
||||
return WriteElements(w, a.ExtraOpaqueData)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
// wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *ChannelUpdate) MsgType() MessageType {
|
||||
return MsgChannelUpdate
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload size for this message
|
||||
// observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *ChannelUpdate) MaxPayloadLength(pver uint32) uint32 {
|
||||
return 65533
|
||||
}
|
||||
|
||||
// DataToSign is used to retrieve part of the announcement message which should
|
||||
// be signed.
|
||||
func (a *ChannelUpdate) DataToSign() ([]byte, error) {
|
||||
|
||||
// We should not include the signatures itself.
|
||||
var w bytes.Buffer
|
||||
err := WriteElements(&w,
|
||||
a.ChainHash[:],
|
||||
a.ShortChannelID,
|
||||
a.Timestamp,
|
||||
a.MessageFlags,
|
||||
a.ChannelFlags,
|
||||
a.TimeLockDelta,
|
||||
a.HtlcMinimumMsat,
|
||||
a.BaseFee,
|
||||
a.FeeRate,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Now append optional fields if they are set. Currently, the only
|
||||
// optional field is max HTLC.
|
||||
if a.MessageFlags.HasMaxHtlc() {
|
||||
if err := WriteElements(&w, a.HtlcMaximumMsat); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, append any extra opaque data.
|
||||
if err := WriteElements(&w, a.ExtraOpaqueData); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return w.Bytes(), nil
|
||||
}
|
||||
88
vendor/github.com/lightningnetwork/lnd/lnwire/closing_signed.go
generated
vendored
Normal file
88
vendor/github.com/lightningnetwork/lnd/lnwire/closing_signed.go
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcutil"
|
||||
)
|
||||
|
||||
// ClosingSigned is sent by both parties to a channel once the channel is clear
|
||||
// of HTLCs, and is primarily concerned with negotiating fees for the close
|
||||
// transaction. Each party provides a signature for a transaction with a fee
|
||||
// that they believe is fair. The process terminates when both sides agree on
|
||||
// the same fee, or when one side force closes the channel.
|
||||
//
|
||||
// NOTE: The responder is able to send a signature without any additional
|
||||
// messages as all transactions are assembled observing BIP 69 which defines a
|
||||
// canonical ordering for input/outputs. Therefore, both sides are able to
|
||||
// arrive at an identical closure transaction as they know the order of the
|
||||
// inputs/outputs.
|
||||
type ClosingSigned struct {
|
||||
// ChannelID serves to identify which channel is to be closed.
|
||||
ChannelID ChannelID
|
||||
|
||||
// FeeSatoshis is the total fee in satoshis that the party to the
|
||||
// channel would like to propose for the close transaction.
|
||||
FeeSatoshis btcutil.Amount
|
||||
|
||||
// Signature is for the proposed channel close transaction.
|
||||
Signature Sig
|
||||
}
|
||||
|
||||
// NewClosingSigned creates a new empty ClosingSigned message.
|
||||
func NewClosingSigned(cid ChannelID, fs btcutil.Amount,
|
||||
sig Sig) *ClosingSigned {
|
||||
|
||||
return &ClosingSigned{
|
||||
ChannelID: cid,
|
||||
FeeSatoshis: fs,
|
||||
Signature: sig,
|
||||
}
|
||||
}
|
||||
|
||||
// A compile time check to ensure ClosingSigned implements the lnwire.Message
|
||||
// interface.
|
||||
var _ Message = (*ClosingSigned)(nil)
|
||||
|
||||
// Decode deserializes a serialized ClosingSigned message stored in the passed
|
||||
// io.Reader observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *ClosingSigned) Decode(r io.Reader, pver uint32) error {
|
||||
return ReadElements(r, &c.ChannelID, &c.FeeSatoshis, &c.Signature)
|
||||
}
|
||||
|
||||
// Encode serializes the target ClosingSigned into the passed io.Writer
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *ClosingSigned) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w, c.ChannelID, c.FeeSatoshis, c.Signature)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
// wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *ClosingSigned) MsgType() MessageType {
|
||||
return MsgClosingSigned
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload size for a
|
||||
// ClosingSigned complete message observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *ClosingSigned) MaxPayloadLength(uint32) uint32 {
|
||||
var length uint32
|
||||
|
||||
// ChannelID - 32 bytes
|
||||
length += 32
|
||||
|
||||
// FeeSatoshis - 8 bytes
|
||||
length += 8
|
||||
|
||||
// Signature - 64 bytes
|
||||
length += 64
|
||||
|
||||
return length
|
||||
}
|
||||
85
vendor/github.com/lightningnetwork/lnd/lnwire/commit_sig.go
generated
vendored
Normal file
85
vendor/github.com/lightningnetwork/lnd/lnwire/commit_sig.go
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
package lnwire
|
||||
|
||||
import "io"
|
||||
|
||||
// CommitSig is sent by either side to stage any pending HTLC's in the
|
||||
// receiver's pending set into a new commitment state. Implicitly, the new
|
||||
// commitment transaction constructed which has been signed by CommitSig
|
||||
// includes all HTLC's in the remote node's pending set. A CommitSig message
|
||||
// may be sent after a series of UpdateAddHTLC/UpdateFulfillHTLC messages in
|
||||
// order to batch add several HTLC's with a single signature covering all
|
||||
// implicitly accepted HTLC's.
|
||||
type CommitSig struct {
|
||||
// ChanID uniquely identifies to which currently active channel this
|
||||
// CommitSig applies to.
|
||||
ChanID ChannelID
|
||||
|
||||
// CommitSig is Alice's signature for Bob's new commitment transaction.
|
||||
// Alice is able to send this signature without requesting any
|
||||
// additional data due to the piggybacking of Bob's next revocation
|
||||
// hash in his prior RevokeAndAck message, as well as the canonical
|
||||
// ordering used for all inputs/outputs within commitment transactions.
|
||||
// If initiating a new commitment state, this signature should ONLY
|
||||
// cover all of the sending party's pending log updates, and the log
|
||||
// updates of the remote party that have been ACK'd.
|
||||
CommitSig Sig
|
||||
|
||||
// HtlcSigs is a signature for each relevant HTLC output within the
|
||||
// created commitment. The order of the signatures is expected to be
|
||||
// identical to the placement of the HTLC's within the BIP 69 sorted
|
||||
// commitment transaction. For each outgoing HTLC (from the PoV of the
|
||||
// sender of this message), a signature for an HTLC timeout transaction
|
||||
// should be signed, for each incoming HTLC the HTLC timeout
|
||||
// transaction should be signed.
|
||||
HtlcSigs []Sig
|
||||
}
|
||||
|
||||
// NewCommitSig creates a new empty CommitSig message.
|
||||
func NewCommitSig() *CommitSig {
|
||||
return &CommitSig{}
|
||||
}
|
||||
|
||||
// A compile time check to ensure CommitSig implements the lnwire.Message
|
||||
// interface.
|
||||
var _ Message = (*CommitSig)(nil)
|
||||
|
||||
// Decode deserializes a serialized CommitSig message stored in the
|
||||
// passed io.Reader observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *CommitSig) Decode(r io.Reader, pver uint32) error {
|
||||
return ReadElements(r,
|
||||
&c.ChanID,
|
||||
&c.CommitSig,
|
||||
&c.HtlcSigs,
|
||||
)
|
||||
}
|
||||
|
||||
// Encode serializes the target CommitSig into the passed io.Writer
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *CommitSig) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
c.ChanID,
|
||||
c.CommitSig,
|
||||
c.HtlcSigs,
|
||||
)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
// wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *CommitSig) MsgType() MessageType {
|
||||
return MsgCommitSig
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload size for a
|
||||
// CommitSig complete message observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *CommitSig) MaxPayloadLength(uint32) uint32 {
|
||||
// 32 + 64 + 2 + max_allowed_htlcs
|
||||
return MaxMessagePayload
|
||||
}
|
||||
127
vendor/github.com/lightningnetwork/lnd/lnwire/error.go
generated
vendored
Normal file
127
vendor/github.com/lightningnetwork/lnd/lnwire/error.go
generated
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
)
|
||||
|
||||
// ErrorCode represents the short error code for each of the defined errors
|
||||
// within the Lightning Network protocol spec.
|
||||
type ErrorCode uint8
|
||||
|
||||
// ToGrpcCode is used to generate gRPC specific code which will be propagated
|
||||
// to the ln rpc client. This code is used to have more detailed view of what
|
||||
// goes wrong and also in order to have the ability pragmatically determine the
|
||||
// error and take specific actions on the client side.
|
||||
func (e ErrorCode) ToGrpcCode() codes.Code {
|
||||
return (codes.Code)(e) + 100
|
||||
}
|
||||
|
||||
const (
|
||||
// ErrMaxPendingChannels is returned by remote peer when the number of
|
||||
// active pending channels exceeds their maximum policy limit.
|
||||
ErrMaxPendingChannels ErrorCode = 1
|
||||
|
||||
// ErrSynchronizingChain is returned by a remote peer that receives a
|
||||
// channel update or a funding request while their still syncing to the
|
||||
// latest state of the blockchain.
|
||||
ErrSynchronizingChain ErrorCode = 2
|
||||
|
||||
// ErrChanTooLarge is returned by a remote peer that receives a
|
||||
// FundingOpen request for a channel that is above their current
|
||||
// soft-limit.
|
||||
ErrChanTooLarge ErrorCode = 3
|
||||
)
|
||||
|
||||
// String returns a human readable version of the target ErrorCode.
|
||||
func (e ErrorCode) String() string {
|
||||
switch e {
|
||||
case ErrMaxPendingChannels:
|
||||
return "Number of pending channels exceed maximum"
|
||||
case ErrSynchronizingChain:
|
||||
return "Synchronizing blockchain"
|
||||
case ErrChanTooLarge:
|
||||
return "channel too large"
|
||||
default:
|
||||
return "unknown error"
|
||||
}
|
||||
}
|
||||
|
||||
// Error returns the human redable version of the target ErrorCode.
|
||||
//
|
||||
// Satisfies the Error interface.
|
||||
func (e ErrorCode) Error() string {
|
||||
return e.String()
|
||||
}
|
||||
|
||||
// ErrorData is a set of bytes associated with a particular sent error. A
|
||||
// receiving node SHOULD only print out data verbatim if the string is composed
|
||||
// solely of printable ASCII characters. For reference, the printable character
|
||||
// set includes byte values 32 through 127 inclusive.
|
||||
type ErrorData []byte
|
||||
|
||||
// Error represents a generic error bound to an exact channel. The message
|
||||
// format is purposefully general in order to allow expression of a wide array
|
||||
// of possible errors. Each Error message is directed at a particular open
|
||||
// channel referenced by ChannelPoint.
|
||||
//
|
||||
// TODO(roasbeef): remove the error code
|
||||
type Error struct {
|
||||
// ChanID references the active channel in which the error occurred
|
||||
// within. If the ChanID is all zeros, then this error applies to the
|
||||
// entire established connection.
|
||||
ChanID ChannelID
|
||||
|
||||
// Data is the attached error data that describes the exact failure
|
||||
// which caused the error message to be sent.
|
||||
Data ErrorData
|
||||
}
|
||||
|
||||
// NewError creates a new Error message.
|
||||
func NewError() *Error {
|
||||
return &Error{}
|
||||
}
|
||||
|
||||
// A compile time check to ensure Error implements the lnwire.Message
|
||||
// interface.
|
||||
var _ Message = (*Error)(nil)
|
||||
|
||||
// Decode deserializes a serialized Error message stored in the passed
|
||||
// io.Reader observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *Error) Decode(r io.Reader, pver uint32) error {
|
||||
return ReadElements(r,
|
||||
&c.ChanID,
|
||||
&c.Data,
|
||||
)
|
||||
}
|
||||
|
||||
// Encode serializes the target Error into the passed io.Writer observing the
|
||||
// protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *Error) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
c.ChanID,
|
||||
c.Data,
|
||||
)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying an Error message on the
|
||||
// wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *Error) MsgType() MessageType {
|
||||
return MsgError
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload size for an Error
|
||||
// complete message observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *Error) MaxPayloadLength(uint32) uint32 {
|
||||
// 32 + 2 + 65501
|
||||
return 65535
|
||||
}
|
||||
263
vendor/github.com/lightningnetwork/lnd/lnwire/features.go
generated
vendored
Normal file
263
vendor/github.com/lightningnetwork/lnd/lnwire/features.go
generated
vendored
Normal file
@@ -0,0 +1,263 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// FeatureBit represents a feature that can be enabled in either a local or
|
||||
// global feature vector at a specific bit position. Feature bits follow the
|
||||
// "it's OK to be odd" rule, where features at even bit positions must be known
|
||||
// to a node receiving them from a peer while odd bits do not. In accordance,
|
||||
// feature bits are usually assigned in pairs, first being assigned an odd bit
|
||||
// position which may later be changed to the preceding even position once
|
||||
// knowledge of the feature becomes required on the network.
|
||||
type FeatureBit uint16
|
||||
|
||||
const (
|
||||
// DataLossProtectRequired is a feature bit that indicates that a peer
|
||||
// *requires* the other party know about the data-loss-protect optional
|
||||
// feature. If the remote peer does not know of such a feature, then
|
||||
// the sending peer SHOLUD disconnect them. The data-loss-protect
|
||||
// feature allows a peer that's lost partial data to recover their
|
||||
// settled funds of the latest commitment state.
|
||||
DataLossProtectRequired FeatureBit = 0
|
||||
|
||||
// DataLossProtectOptional is an optional feature bit that indicates
|
||||
// that the sending peer knows of this new feature and can activate it
|
||||
// it. The data-loss-protect feature allows a peer that's lost partial
|
||||
// data to recover their settled funds of the latest commitment state.
|
||||
DataLossProtectOptional FeatureBit = 1
|
||||
|
||||
// InitialRoutingSync is a local feature bit meaning that the receiving
|
||||
// node should send a complete dump of routing information when a new
|
||||
// connection is established.
|
||||
InitialRoutingSync FeatureBit = 3
|
||||
|
||||
// GossipQueriesRequired is a feature bit that indicates that the
|
||||
// receiving peer MUST know of the set of features that allows nodes to
|
||||
// more efficiently query the network view of peers on the network for
|
||||
// reconciliation purposes.
|
||||
GossipQueriesRequired FeatureBit = 6
|
||||
|
||||
// GossipQueriesOptional is an optional feature bit that signals that
|
||||
// the setting peer knows of the set of features that allows more
|
||||
// efficient network view reconciliation.
|
||||
GossipQueriesOptional FeatureBit = 7
|
||||
|
||||
// maxAllowedSize is a maximum allowed size of feature vector.
|
||||
//
|
||||
// NOTE: Within the protocol, the maximum allowed message size is 65535
|
||||
// bytes for all messages. Accounting for the overhead within the feature
|
||||
// message to signal the type of message, that leaves us with 65533 bytes
|
||||
// for the init message itself. Next, we reserve 4 bytes to encode the
|
||||
// lengths of both the local and global feature vectors, so 65529 bytes
|
||||
// for the local and global features. Knocking off one byte for the sake
|
||||
// of the calculation, that leads us to 32764 bytes for each feature
|
||||
// vector, or 131056 different features.
|
||||
maxAllowedSize = 32764
|
||||
)
|
||||
|
||||
// LocalFeatures is a mapping of known connection-local feature bits to a
|
||||
// descriptive name. All known local feature bits must be assigned a name in
|
||||
// this mapping. Local features are those which are only sent to the peer and
|
||||
// not advertised to the entire network. A full description of these feature
|
||||
// bits is provided in the BOLT-09 specification.
|
||||
var LocalFeatures = map[FeatureBit]string{
|
||||
DataLossProtectRequired: "data-loss-protect",
|
||||
DataLossProtectOptional: "data-loss-protect",
|
||||
InitialRoutingSync: "initial-routing-sync",
|
||||
GossipQueriesRequired: "gossip-queries",
|
||||
GossipQueriesOptional: "gossip-queries",
|
||||
}
|
||||
|
||||
// GlobalFeatures is a mapping of known global feature bits to a descriptive
|
||||
// name. All known global feature bits must be assigned a name in this mapping.
|
||||
// Global features are those which are advertised to the entire network. A full
|
||||
// description of these feature bits is provided in the BOLT-09 specification.
|
||||
var GlobalFeatures map[FeatureBit]string
|
||||
|
||||
// RawFeatureVector represents a set of feature bits as defined in BOLT-09. A
|
||||
// RawFeatureVector itself just stores a set of bit flags but can be used to
|
||||
// construct a FeatureVector which binds meaning to each bit. Feature vectors
|
||||
// can be serialized and deserialized to/from a byte representation that is
|
||||
// transmitted in Lightning network messages.
|
||||
type RawFeatureVector struct {
|
||||
features map[FeatureBit]bool
|
||||
}
|
||||
|
||||
// NewRawFeatureVector creates a feature vector with all of the feature bits
|
||||
// given as arguments enabled.
|
||||
func NewRawFeatureVector(bits ...FeatureBit) *RawFeatureVector {
|
||||
fv := &RawFeatureVector{features: make(map[FeatureBit]bool)}
|
||||
for _, bit := range bits {
|
||||
fv.Set(bit)
|
||||
}
|
||||
return fv
|
||||
}
|
||||
|
||||
// IsSet returns whether a particular feature bit is enabled in the vector.
|
||||
func (fv *RawFeatureVector) IsSet(feature FeatureBit) bool {
|
||||
return fv.features[feature]
|
||||
}
|
||||
|
||||
// Set marks a feature as enabled in the vector.
|
||||
func (fv *RawFeatureVector) Set(feature FeatureBit) {
|
||||
fv.features[feature] = true
|
||||
}
|
||||
|
||||
// Unset marks a feature as disabled in the vector.
|
||||
func (fv *RawFeatureVector) Unset(feature FeatureBit) {
|
||||
delete(fv.features, feature)
|
||||
}
|
||||
|
||||
// SerializeSize returns the number of bytes needed to represent feature vector
|
||||
// in byte format.
|
||||
func (fv *RawFeatureVector) SerializeSize() int {
|
||||
// Find the largest feature bit index
|
||||
max := -1
|
||||
for feature := range fv.features {
|
||||
index := int(feature)
|
||||
if index > max {
|
||||
max = index
|
||||
}
|
||||
}
|
||||
if max == -1 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// We calculate byte-length via the largest bit index
|
||||
return max/8 + 1
|
||||
}
|
||||
|
||||
// Encode writes the feature vector in byte representation. Every feature
|
||||
// encoded as a bit, and the bit vector is serialized using the least number of
|
||||
// bytes. Since the bit vector length is variable, the first two bytes of the
|
||||
// serialization represent the length.
|
||||
func (fv *RawFeatureVector) Encode(w io.Writer) error {
|
||||
// Write length of feature vector.
|
||||
var l [2]byte
|
||||
length := fv.SerializeSize()
|
||||
binary.BigEndian.PutUint16(l[:], uint16(length))
|
||||
if _, err := w.Write(l[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Generate the data and write it.
|
||||
data := make([]byte, length)
|
||||
for feature := range fv.features {
|
||||
byteIndex := int(feature / 8)
|
||||
bitIndex := feature % 8
|
||||
data[length-byteIndex-1] |= 1 << bitIndex
|
||||
}
|
||||
|
||||
_, err := w.Write(data)
|
||||
return err
|
||||
}
|
||||
|
||||
// Decode reads the feature vector from its byte representation. Every feature
|
||||
// encoded as a bit, and the bit vector is serialized using the least number of
|
||||
// bytes. Since the bit vector length is variable, the first two bytes of the
|
||||
// serialization represent the length.
|
||||
func (fv *RawFeatureVector) Decode(r io.Reader) error {
|
||||
// Read the length of the feature vector.
|
||||
var l [2]byte
|
||||
if _, err := io.ReadFull(r, l[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
length := binary.BigEndian.Uint16(l[:])
|
||||
|
||||
// Read the feature vector data.
|
||||
data := make([]byte, length)
|
||||
if _, err := io.ReadFull(r, data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Set feature bits from parsed data.
|
||||
bitsNumber := len(data) * 8
|
||||
for i := 0; i < bitsNumber; i++ {
|
||||
byteIndex := uint16(i / 8)
|
||||
bitIndex := uint(i % 8)
|
||||
if (data[length-byteIndex-1]>>bitIndex)&1 == 1 {
|
||||
fv.Set(FeatureBit(i))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FeatureVector represents a set of enabled features. The set stores
|
||||
// information on enabled flags and metadata about the feature names. A feature
|
||||
// vector is serializable to a compact byte representation that is included in
|
||||
// Lightning network messages.
|
||||
type FeatureVector struct {
|
||||
*RawFeatureVector
|
||||
featureNames map[FeatureBit]string
|
||||
}
|
||||
|
||||
// NewFeatureVector constructs a new FeatureVector from a raw feature vector
|
||||
// and mapping of feature definitions. If the feature vector argument is nil, a
|
||||
// new one will be constructed with no enabled features.
|
||||
func NewFeatureVector(featureVector *RawFeatureVector,
|
||||
featureNames map[FeatureBit]string) *FeatureVector {
|
||||
|
||||
if featureVector == nil {
|
||||
featureVector = NewRawFeatureVector()
|
||||
}
|
||||
return &FeatureVector{
|
||||
RawFeatureVector: featureVector,
|
||||
featureNames: featureNames,
|
||||
}
|
||||
}
|
||||
|
||||
// HasFeature returns whether a particular feature is included in the set. The
|
||||
// feature can be seen as set either if the bit is set directly OR the queried
|
||||
// bit has the same meaning as its corresponding even/odd bit, which is set
|
||||
// instead. The second case is because feature bits are generally assigned in
|
||||
// pairs where both the even and odd position represent the same feature.
|
||||
func (fv *FeatureVector) HasFeature(feature FeatureBit) bool {
|
||||
return fv.IsSet(feature) ||
|
||||
(fv.isFeatureBitPair(feature) && fv.IsSet(feature^1))
|
||||
}
|
||||
|
||||
// UnknownRequiredFeatures returns a list of feature bits set in the vector
|
||||
// that are unknown and in an even bit position. Feature bits with an even
|
||||
// index must be known to a node receiving the feature vector in a message.
|
||||
func (fv *FeatureVector) UnknownRequiredFeatures() []FeatureBit {
|
||||
var unknown []FeatureBit
|
||||
for feature := range fv.features {
|
||||
if feature%2 == 0 && !fv.IsKnown(feature) {
|
||||
unknown = append(unknown, feature)
|
||||
}
|
||||
}
|
||||
return unknown
|
||||
}
|
||||
|
||||
// Name returns a string identifier for the feature represented by this bit. If
|
||||
// the bit does not represent a known feature, this returns a string indicating
|
||||
// as much.
|
||||
func (fv *FeatureVector) Name(bit FeatureBit) string {
|
||||
name, known := fv.featureNames[bit]
|
||||
if !known {
|
||||
name = "unknown"
|
||||
}
|
||||
return fmt.Sprintf("%s(%d)", name, bit)
|
||||
}
|
||||
|
||||
// IsKnown returns whether this feature bit represents a known feature.
|
||||
func (fv *FeatureVector) IsKnown(bit FeatureBit) bool {
|
||||
_, known := fv.featureNames[bit]
|
||||
return known
|
||||
}
|
||||
|
||||
// isFeatureBitPair returns whether this feature bit and its corresponding
|
||||
// even/odd bit both represent the same feature. This may often be the case as
|
||||
// bits are generally assigned in pairs, first being assigned an odd bit
|
||||
// position then being promoted to an even bit position once the network is
|
||||
// ready.
|
||||
func (fv *FeatureVector) isFeatureBitPair(bit FeatureBit) bool {
|
||||
name1, known1 := fv.featureNames[bit]
|
||||
name2, known2 := fv.featureNames[bit^1]
|
||||
return known1 && known2 && name1 == name2
|
||||
}
|
||||
66
vendor/github.com/lightningnetwork/lnd/lnwire/funding_created.go
generated
vendored
Normal file
66
vendor/github.com/lightningnetwork/lnd/lnwire/funding_created.go
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
)
|
||||
|
||||
// FundingCreated is sent from Alice (the initiator) to Bob (the responder),
|
||||
// once Alice receives Bob's contributions as well as his channel constraints.
|
||||
// Once bob receives this message, he'll gain access to an immediately
|
||||
// broadcastable commitment transaction and will reply with a signature for
|
||||
// Alice's version of the commitment transaction.
|
||||
type FundingCreated struct {
|
||||
// PendingChannelID serves to uniquely identify the future channel
|
||||
// created by the initiated single funder workflow.
|
||||
PendingChannelID [32]byte
|
||||
|
||||
// FundingPoint is the outpoint of the funding transaction created by
|
||||
// Alice. With this, Bob is able to generate both his version and
|
||||
// Alice's version of the commitment transaction.
|
||||
FundingPoint wire.OutPoint
|
||||
|
||||
// CommitSig is Alice's signature from Bob's version of the commitment
|
||||
// transaction.
|
||||
CommitSig Sig
|
||||
}
|
||||
|
||||
// A compile time check to ensure FundingCreated implements the lnwire.Message
|
||||
// interface.
|
||||
var _ Message = (*FundingCreated)(nil)
|
||||
|
||||
// Encode serializes the target FundingCreated into the passed io.Writer
|
||||
// implementation. Serialization will observe the rules defined by the passed
|
||||
// protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (f *FundingCreated) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w, f.PendingChannelID[:], f.FundingPoint, f.CommitSig)
|
||||
}
|
||||
|
||||
// Decode deserializes the serialized FundingCreated stored in the passed
|
||||
// io.Reader into the target FundingCreated using the deserialization rules
|
||||
// defined by the passed protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (f *FundingCreated) Decode(r io.Reader, pver uint32) error {
|
||||
return ReadElements(r, f.PendingChannelID[:], &f.FundingPoint, &f.CommitSig)
|
||||
}
|
||||
|
||||
// MsgType returns the uint32 code which uniquely identifies this message as a
|
||||
// FundingCreated on the wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (f *FundingCreated) MsgType() MessageType {
|
||||
return MsgFundingCreated
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload length for a
|
||||
// FundingCreated message.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (f *FundingCreated) MaxPayloadLength(uint32) uint32 {
|
||||
// 32 + 32 + 2 + 64
|
||||
return 130
|
||||
}
|
||||
83
vendor/github.com/lightningnetwork/lnd/lnwire/funding_locked.go
generated
vendored
Normal file
83
vendor/github.com/lightningnetwork/lnd/lnwire/funding_locked.go
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
)
|
||||
|
||||
// FundingLocked is the message that both parties to a new channel creation
|
||||
// send once they have observed the funding transaction being confirmed on the
|
||||
// blockchain. FundingLocked contains the signatures necessary for the channel
|
||||
// participants to advertise the existence of the channel to the rest of the
|
||||
// network.
|
||||
type FundingLocked struct {
|
||||
// ChanID is the outpoint of the channel's funding transaction. This
|
||||
// can be used to query for the channel in the database.
|
||||
ChanID ChannelID
|
||||
|
||||
// NextPerCommitmentPoint is the secret that can be used to revoke the
|
||||
// next commitment transaction for the channel.
|
||||
NextPerCommitmentPoint *btcec.PublicKey
|
||||
}
|
||||
|
||||
// NewFundingLocked creates a new FundingLocked message, populating it with the
|
||||
// necessary IDs and revocation secret.
|
||||
func NewFundingLocked(cid ChannelID, npcp *btcec.PublicKey) *FundingLocked {
|
||||
return &FundingLocked{
|
||||
ChanID: cid,
|
||||
NextPerCommitmentPoint: npcp,
|
||||
}
|
||||
}
|
||||
|
||||
// A compile time check to ensure FundingLocked implements the lnwire.Message
|
||||
// interface.
|
||||
var _ Message = (*FundingLocked)(nil)
|
||||
|
||||
// Decode deserializes the serialized FundingLocked message stored in the
|
||||
// passed io.Reader into the target FundingLocked using the deserialization
|
||||
// rules defined by the passed protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *FundingLocked) Decode(r io.Reader, pver uint32) error {
|
||||
return ReadElements(r,
|
||||
&c.ChanID,
|
||||
&c.NextPerCommitmentPoint)
|
||||
}
|
||||
|
||||
// Encode serializes the target FundingLocked message into the passed io.Writer
|
||||
// implementation. Serialization will observe the rules defined by the passed
|
||||
// protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *FundingLocked) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
c.ChanID,
|
||||
c.NextPerCommitmentPoint)
|
||||
}
|
||||
|
||||
// MsgType returns the uint32 code which uniquely identifies this message as a
|
||||
// FundingLocked message on the wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *FundingLocked) MsgType() MessageType {
|
||||
return MsgFundingLocked
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload length for a
|
||||
// FundingLocked message. This is calculated by summing the max length of all
|
||||
// the fields within a FundingLocked message.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *FundingLocked) MaxPayloadLength(uint32) uint32 {
|
||||
var length uint32
|
||||
|
||||
// ChanID - 32 bytes
|
||||
length += 32
|
||||
|
||||
// NextPerCommitmentPoint - 33 bytes
|
||||
length += 33
|
||||
|
||||
// 65 bytes
|
||||
return length
|
||||
}
|
||||
55
vendor/github.com/lightningnetwork/lnd/lnwire/funding_signed.go
generated
vendored
Normal file
55
vendor/github.com/lightningnetwork/lnd/lnwire/funding_signed.go
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
package lnwire
|
||||
|
||||
import "io"
|
||||
|
||||
// FundingSigned is sent from Bob (the responder) to Alice (the initiator)
|
||||
// after receiving the funding outpoint and her signature for Bob's version of
|
||||
// the commitment transaction.
|
||||
type FundingSigned struct {
|
||||
// ChannelPoint is the particular active channel that this
|
||||
// FundingSigned is bound to.
|
||||
ChanID ChannelID
|
||||
|
||||
// CommitSig is Bob's signature for Alice's version of the commitment
|
||||
// transaction.
|
||||
CommitSig Sig
|
||||
}
|
||||
|
||||
// A compile time check to ensure FundingSigned implements the lnwire.Message
|
||||
// interface.
|
||||
var _ Message = (*FundingSigned)(nil)
|
||||
|
||||
// Encode serializes the target FundingSigned into the passed io.Writer
|
||||
// implementation. Serialization will observe the rules defined by the passed
|
||||
// protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (f *FundingSigned) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w, f.ChanID, f.CommitSig)
|
||||
}
|
||||
|
||||
// Decode deserializes the serialized FundingSigned stored in the passed
|
||||
// io.Reader into the target FundingSigned using the deserialization rules
|
||||
// defined by the passed protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (f *FundingSigned) Decode(r io.Reader, pver uint32) error {
|
||||
return ReadElements(r, &f.ChanID, &f.CommitSig)
|
||||
}
|
||||
|
||||
// MsgType returns the uint32 code which uniquely identifies this message as a
|
||||
// FundingSigned on the wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (f *FundingSigned) MsgType() MessageType {
|
||||
return MsgFundingSigned
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload length for a
|
||||
// FundingSigned message.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (f *FundingSigned) MaxPayloadLength(uint32) uint32 {
|
||||
// 32 + 64
|
||||
return 96
|
||||
}
|
||||
80
vendor/github.com/lightningnetwork/lnd/lnwire/gossip_timestamp_range.go
generated
vendored
Normal file
80
vendor/github.com/lightningnetwork/lnd/lnwire/gossip_timestamp_range.go
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
)
|
||||
|
||||
// GossipTimestampRange is a message that allows the sender to restrict the set
|
||||
// of future gossip announcements sent by the receiver. Nodes should send this
|
||||
// if they have the gossip-queries feature bit active. Nodes are able to send
|
||||
// new GossipTimestampRange messages to replace the prior window.
|
||||
type GossipTimestampRange struct {
|
||||
// ChainHash denotes the chain that the sender wishes to restrict the
|
||||
// set of received announcements of.
|
||||
ChainHash chainhash.Hash
|
||||
|
||||
// FirstTimestamp is the timestamp of the earliest announcement message
|
||||
// that should be sent by the receiver.
|
||||
FirstTimestamp uint32
|
||||
|
||||
// TimestampRange is the horizon beyond the FirstTimestamp that any
|
||||
// announcement messages should be sent for. The receiving node MUST
|
||||
// NOT send any announcements that have a timestamp greater than
|
||||
// FirstTimestamp + TimestampRange.
|
||||
TimestampRange uint32
|
||||
}
|
||||
|
||||
// NewGossipTimestampRange creates a new empty GossipTimestampRange message.
|
||||
func NewGossipTimestampRange() *GossipTimestampRange {
|
||||
return &GossipTimestampRange{}
|
||||
}
|
||||
|
||||
// A compile time check to ensure GossipTimestampRange implements the
|
||||
// lnwire.Message interface.
|
||||
var _ Message = (*GossipTimestampRange)(nil)
|
||||
|
||||
// Decode deserializes a serialized GossipTimestampRange message stored in the
|
||||
// passed io.Reader observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (g *GossipTimestampRange) Decode(r io.Reader, pver uint32) error {
|
||||
return ReadElements(r,
|
||||
g.ChainHash[:],
|
||||
&g.FirstTimestamp,
|
||||
&g.TimestampRange,
|
||||
)
|
||||
}
|
||||
|
||||
// Encode serializes the target GossipTimestampRange into the passed io.Writer
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (g *GossipTimestampRange) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
g.ChainHash[:],
|
||||
g.FirstTimestamp,
|
||||
g.TimestampRange,
|
||||
)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
// wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (g *GossipTimestampRange) MsgType() MessageType {
|
||||
return MsgGossipTimestampRange
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload size for a
|
||||
// GossipTimestampRange complete message observing the specified protocol
|
||||
// version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (g *GossipTimestampRange) MaxPayloadLength(uint32) uint32 {
|
||||
// 32 + 4 + 4
|
||||
//
|
||||
// TODO(roasbeef): update to 8 byte timestmaps?
|
||||
return 40
|
||||
}
|
||||
67
vendor/github.com/lightningnetwork/lnd/lnwire/init_message.go
generated
vendored
Normal file
67
vendor/github.com/lightningnetwork/lnd/lnwire/init_message.go
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
package lnwire
|
||||
|
||||
import "io"
|
||||
|
||||
// Init is the first message reveals the features supported or required by this
|
||||
// node. Nodes wait for receipt of the other's features to simplify error
|
||||
// diagnosis where features are incompatible. Each node MUST wait to receive
|
||||
// init before sending any other messages.
|
||||
type Init struct {
|
||||
// GlobalFeatures is feature vector which affects HTLCs and thus are
|
||||
// also advertised to other nodes.
|
||||
GlobalFeatures *RawFeatureVector
|
||||
|
||||
// LocalFeatures is feature vector which only affect the protocol
|
||||
// between two nodes.
|
||||
LocalFeatures *RawFeatureVector
|
||||
}
|
||||
|
||||
// NewInitMessage creates new instance of init message object.
|
||||
func NewInitMessage(gf *RawFeatureVector, lf *RawFeatureVector) *Init {
|
||||
return &Init{
|
||||
GlobalFeatures: gf,
|
||||
LocalFeatures: lf,
|
||||
}
|
||||
}
|
||||
|
||||
// A compile time check to ensure Init implements the lnwire.Message
|
||||
// interface.
|
||||
var _ Message = (*Init)(nil)
|
||||
|
||||
// Decode deserializes a serialized Init message stored in the passed
|
||||
// io.Reader observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (msg *Init) Decode(r io.Reader, pver uint32) error {
|
||||
return ReadElements(r,
|
||||
&msg.GlobalFeatures,
|
||||
&msg.LocalFeatures,
|
||||
)
|
||||
}
|
||||
|
||||
// Encode serializes the target Init into the passed io.Writer observing
|
||||
// the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (msg *Init) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
msg.GlobalFeatures,
|
||||
msg.LocalFeatures,
|
||||
)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
// wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (msg *Init) MsgType() MessageType {
|
||||
return MsgInit
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload size for an Init
|
||||
// complete message observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (msg *Init) MaxPayloadLength(uint32) uint32 {
|
||||
return 2 + 2 + maxAllowedSize + 2 + maxAllowedSize
|
||||
}
|
||||
857
vendor/github.com/lightningnetwork/lnd/lnwire/lnwire.go
generated
vendored
Normal file
857
vendor/github.com/lightningnetwork/lnd/lnwire/lnwire.go
generated
vendored
Normal file
@@ -0,0 +1,857 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"image/color"
|
||||
"io"
|
||||
"math"
|
||||
|
||||
"net"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/lightningnetwork/lnd/tor"
|
||||
)
|
||||
|
||||
// MaxSliceLength is the maximum allowed length for any opaque byte slices in
|
||||
// the wire protocol.
|
||||
const MaxSliceLength = 65535
|
||||
|
||||
// PkScript is simple type definition which represents a raw serialized public
|
||||
// key script.
|
||||
type PkScript []byte
|
||||
|
||||
// addressType specifies the network protocol and version that should be used
|
||||
// when connecting to a node at a particular address.
|
||||
type addressType uint8
|
||||
|
||||
const (
|
||||
// noAddr denotes a blank address. An address of this type indicates
|
||||
// that a node doesn't have any advertised addresses.
|
||||
noAddr addressType = 0
|
||||
|
||||
// tcp4Addr denotes an IPv4 TCP address.
|
||||
tcp4Addr addressType = 1
|
||||
|
||||
// tcp6Addr denotes an IPv6 TCP address.
|
||||
tcp6Addr addressType = 2
|
||||
|
||||
// v2OnionAddr denotes a version 2 Tor onion service address.
|
||||
v2OnionAddr addressType = 3
|
||||
|
||||
// v3OnionAddr denotes a version 3 Tor (prop224) onion service address.
|
||||
v3OnionAddr addressType = 4
|
||||
)
|
||||
|
||||
// AddrLen returns the number of bytes that it takes to encode the target
|
||||
// address.
|
||||
func (a addressType) AddrLen() uint16 {
|
||||
switch a {
|
||||
case noAddr:
|
||||
return 0
|
||||
case tcp4Addr:
|
||||
return 6
|
||||
case tcp6Addr:
|
||||
return 18
|
||||
case v2OnionAddr:
|
||||
return 12
|
||||
case v3OnionAddr:
|
||||
return 37
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
// WriteElement is a one-stop shop to write the big endian representation of
|
||||
// any element which is to be serialized for the wire protocol. The passed
|
||||
// io.Writer should be backed by an appropriately sized byte slice, or be able
|
||||
// to dynamically expand to accommodate additional data.
|
||||
//
|
||||
// TODO(roasbeef): this should eventually draw from a buffer pool for
|
||||
// serialization.
|
||||
func WriteElement(w io.Writer, element interface{}) error {
|
||||
switch e := element.(type) {
|
||||
case NodeAlias:
|
||||
if _, err := w.Write(e[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case ShortChanIDEncoding:
|
||||
var b [1]byte
|
||||
b[0] = uint8(e)
|
||||
if _, err := w.Write(b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case uint8:
|
||||
var b [1]byte
|
||||
b[0] = e
|
||||
if _, err := w.Write(b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case FundingFlag:
|
||||
var b [1]byte
|
||||
b[0] = uint8(e)
|
||||
if _, err := w.Write(b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case uint16:
|
||||
var b [2]byte
|
||||
binary.BigEndian.PutUint16(b[:], e)
|
||||
if _, err := w.Write(b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case ChanUpdateMsgFlags:
|
||||
var b [1]byte
|
||||
b[0] = uint8(e)
|
||||
if _, err := w.Write(b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case ChanUpdateChanFlags:
|
||||
var b [1]byte
|
||||
b[0] = uint8(e)
|
||||
if _, err := w.Write(b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case ErrorCode:
|
||||
var b [2]byte
|
||||
binary.BigEndian.PutUint16(b[:], uint16(e))
|
||||
if _, err := w.Write(b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case MilliSatoshi:
|
||||
var b [8]byte
|
||||
binary.BigEndian.PutUint64(b[:], uint64(e))
|
||||
if _, err := w.Write(b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case btcutil.Amount:
|
||||
var b [8]byte
|
||||
binary.BigEndian.PutUint64(b[:], uint64(e))
|
||||
if _, err := w.Write(b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case uint32:
|
||||
var b [4]byte
|
||||
binary.BigEndian.PutUint32(b[:], e)
|
||||
if _, err := w.Write(b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case uint64:
|
||||
var b [8]byte
|
||||
binary.BigEndian.PutUint64(b[:], e)
|
||||
if _, err := w.Write(b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case *btcec.PublicKey:
|
||||
if e == nil {
|
||||
return fmt.Errorf("cannot write nil pubkey")
|
||||
}
|
||||
|
||||
var b [33]byte
|
||||
serializedPubkey := e.SerializeCompressed()
|
||||
copy(b[:], serializedPubkey)
|
||||
if _, err := w.Write(b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case []Sig:
|
||||
var b [2]byte
|
||||
numSigs := uint16(len(e))
|
||||
binary.BigEndian.PutUint16(b[:], numSigs)
|
||||
if _, err := w.Write(b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, sig := range e {
|
||||
if err := WriteElement(w, sig); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case Sig:
|
||||
// Write buffer
|
||||
if _, err := w.Write(e[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case PingPayload:
|
||||
var l [2]byte
|
||||
binary.BigEndian.PutUint16(l[:], uint16(len(e)))
|
||||
if _, err := w.Write(l[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := w.Write(e[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case PongPayload:
|
||||
var l [2]byte
|
||||
binary.BigEndian.PutUint16(l[:], uint16(len(e)))
|
||||
if _, err := w.Write(l[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := w.Write(e[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case ErrorData:
|
||||
var l [2]byte
|
||||
binary.BigEndian.PutUint16(l[:], uint16(len(e)))
|
||||
if _, err := w.Write(l[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := w.Write(e[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case OpaqueReason:
|
||||
var l [2]byte
|
||||
binary.BigEndian.PutUint16(l[:], uint16(len(e)))
|
||||
if _, err := w.Write(l[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := w.Write(e[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case [33]byte:
|
||||
if _, err := w.Write(e[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case []byte:
|
||||
if _, err := w.Write(e[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case PkScript:
|
||||
// The largest script we'll accept is a p2wsh which is exactly
|
||||
// 34 bytes long.
|
||||
scriptLength := len(e)
|
||||
if scriptLength > 34 {
|
||||
return fmt.Errorf("'PkScript' too long")
|
||||
}
|
||||
|
||||
if err := wire.WriteVarBytes(w, 0, e); err != nil {
|
||||
return err
|
||||
}
|
||||
case *RawFeatureVector:
|
||||
if e == nil {
|
||||
return fmt.Errorf("cannot write nil feature vector")
|
||||
}
|
||||
|
||||
if err := e.Encode(w); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case wire.OutPoint:
|
||||
var h [32]byte
|
||||
copy(h[:], e.Hash[:])
|
||||
if _, err := w.Write(h[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if e.Index > math.MaxUint16 {
|
||||
return fmt.Errorf("index for outpoint (%v) is "+
|
||||
"greater than max index of %v", e.Index,
|
||||
math.MaxUint16)
|
||||
}
|
||||
|
||||
var idx [2]byte
|
||||
binary.BigEndian.PutUint16(idx[:], uint16(e.Index))
|
||||
if _, err := w.Write(idx[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case ChannelID:
|
||||
if _, err := w.Write(e[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case FailCode:
|
||||
if err := WriteElement(w, uint16(e)); err != nil {
|
||||
return err
|
||||
}
|
||||
case ShortChannelID:
|
||||
// Check that field fit in 3 bytes and write the blockHeight
|
||||
if e.BlockHeight > ((1 << 24) - 1) {
|
||||
return errors.New("block height should fit in 3 bytes")
|
||||
}
|
||||
|
||||
var blockHeight [4]byte
|
||||
binary.BigEndian.PutUint32(blockHeight[:], e.BlockHeight)
|
||||
|
||||
if _, err := w.Write(blockHeight[1:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check that field fit in 3 bytes and write the txIndex
|
||||
if e.TxIndex > ((1 << 24) - 1) {
|
||||
return errors.New("tx index should fit in 3 bytes")
|
||||
}
|
||||
|
||||
var txIndex [4]byte
|
||||
binary.BigEndian.PutUint32(txIndex[:], e.TxIndex)
|
||||
if _, err := w.Write(txIndex[1:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write the txPosition
|
||||
var txPosition [2]byte
|
||||
binary.BigEndian.PutUint16(txPosition[:], e.TxPosition)
|
||||
if _, err := w.Write(txPosition[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case *net.TCPAddr:
|
||||
if e == nil {
|
||||
return fmt.Errorf("cannot write nil TCPAddr")
|
||||
}
|
||||
|
||||
if e.IP.To4() != nil {
|
||||
var descriptor [1]byte
|
||||
descriptor[0] = uint8(tcp4Addr)
|
||||
if _, err := w.Write(descriptor[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var ip [4]byte
|
||||
copy(ip[:], e.IP.To4())
|
||||
if _, err := w.Write(ip[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
var descriptor [1]byte
|
||||
descriptor[0] = uint8(tcp6Addr)
|
||||
if _, err := w.Write(descriptor[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
var ip [16]byte
|
||||
copy(ip[:], e.IP.To16())
|
||||
if _, err := w.Write(ip[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
var port [2]byte
|
||||
binary.BigEndian.PutUint16(port[:], uint16(e.Port))
|
||||
if _, err := w.Write(port[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case *tor.OnionAddr:
|
||||
if e == nil {
|
||||
return errors.New("cannot write nil onion address")
|
||||
}
|
||||
|
||||
var suffixIndex int
|
||||
switch len(e.OnionService) {
|
||||
case tor.V2Len:
|
||||
descriptor := []byte{byte(v2OnionAddr)}
|
||||
if _, err := w.Write(descriptor); err != nil {
|
||||
return err
|
||||
}
|
||||
suffixIndex = tor.V2Len - tor.OnionSuffixLen
|
||||
case tor.V3Len:
|
||||
descriptor := []byte{byte(v3OnionAddr)}
|
||||
if _, err := w.Write(descriptor); err != nil {
|
||||
return err
|
||||
}
|
||||
suffixIndex = tor.V3Len - tor.OnionSuffixLen
|
||||
default:
|
||||
return errors.New("unknown onion service length")
|
||||
}
|
||||
|
||||
host, err := tor.Base32Encoding.DecodeString(
|
||||
e.OnionService[:suffixIndex],
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := w.Write(host); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var port [2]byte
|
||||
binary.BigEndian.PutUint16(port[:], uint16(e.Port))
|
||||
if _, err := w.Write(port[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case []net.Addr:
|
||||
// First, we'll encode all the addresses into an intermediate
|
||||
// buffer. We need to do this in order to compute the total
|
||||
// length of the addresses.
|
||||
var addrBuf bytes.Buffer
|
||||
for _, address := range e {
|
||||
if err := WriteElement(&addrBuf, address); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// With the addresses fully encoded, we can now write out the
|
||||
// number of bytes needed to encode them.
|
||||
addrLen := addrBuf.Len()
|
||||
if err := WriteElement(w, uint16(addrLen)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Finally, we'll write out the raw addresses themselves, but
|
||||
// only if we have any bytes to write.
|
||||
if addrLen > 0 {
|
||||
if _, err := w.Write(addrBuf.Bytes()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case color.RGBA:
|
||||
if err := WriteElements(w, e.R, e.G, e.B); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case DeliveryAddress:
|
||||
var length [2]byte
|
||||
binary.BigEndian.PutUint16(length[:], uint16(len(e)))
|
||||
if _, err := w.Write(length[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := w.Write(e[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case bool:
|
||||
var b [1]byte
|
||||
if e {
|
||||
b[0] = 1
|
||||
}
|
||||
if _, err := w.Write(b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("Unknown type in WriteElement: %T", e)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteElements is writes each element in the elements slice to the passed
|
||||
// io.Writer using WriteElement.
|
||||
func WriteElements(w io.Writer, elements ...interface{}) error {
|
||||
for _, element := range elements {
|
||||
err := WriteElement(w, element)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadElement is a one-stop utility function to deserialize any datastructure
|
||||
// encoded using the serialization format of lnwire.
|
||||
func ReadElement(r io.Reader, element interface{}) error {
|
||||
var err error
|
||||
switch e := element.(type) {
|
||||
case *bool:
|
||||
var b [1]byte
|
||||
if _, err := io.ReadFull(r, b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if b[0] == 1 {
|
||||
*e = true
|
||||
}
|
||||
|
||||
case *NodeAlias:
|
||||
var a [32]byte
|
||||
if _, err := io.ReadFull(r, a[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
alias, err := NewNodeAlias(string(a[:]))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*e = alias
|
||||
case *ShortChanIDEncoding:
|
||||
var b [1]uint8
|
||||
if _, err := r.Read(b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
*e = ShortChanIDEncoding(b[0])
|
||||
case *uint8:
|
||||
var b [1]uint8
|
||||
if _, err := r.Read(b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
*e = b[0]
|
||||
case *FundingFlag:
|
||||
var b [1]uint8
|
||||
if _, err := r.Read(b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
*e = FundingFlag(b[0])
|
||||
case *uint16:
|
||||
var b [2]byte
|
||||
if _, err := io.ReadFull(r, b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
*e = binary.BigEndian.Uint16(b[:])
|
||||
case *ChanUpdateMsgFlags:
|
||||
var b [1]uint8
|
||||
if _, err := r.Read(b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
*e = ChanUpdateMsgFlags(b[0])
|
||||
case *ChanUpdateChanFlags:
|
||||
var b [1]uint8
|
||||
if _, err := r.Read(b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
*e = ChanUpdateChanFlags(b[0])
|
||||
case *ErrorCode:
|
||||
var b [2]byte
|
||||
if _, err := io.ReadFull(r, b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
*e = ErrorCode(binary.BigEndian.Uint16(b[:]))
|
||||
case *uint32:
|
||||
var b [4]byte
|
||||
if _, err := io.ReadFull(r, b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
*e = binary.BigEndian.Uint32(b[:])
|
||||
case *uint64:
|
||||
var b [8]byte
|
||||
if _, err := io.ReadFull(r, b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
*e = binary.BigEndian.Uint64(b[:])
|
||||
case *MilliSatoshi:
|
||||
var b [8]byte
|
||||
if _, err := io.ReadFull(r, b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
*e = MilliSatoshi(int64(binary.BigEndian.Uint64(b[:])))
|
||||
case *btcutil.Amount:
|
||||
var b [8]byte
|
||||
if _, err := io.ReadFull(r, b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
*e = btcutil.Amount(int64(binary.BigEndian.Uint64(b[:])))
|
||||
case **btcec.PublicKey:
|
||||
var b [btcec.PubKeyBytesLenCompressed]byte
|
||||
if _, err = io.ReadFull(r, b[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pubKey, err := btcec.ParsePubKey(b[:], btcec.S256())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*e = pubKey
|
||||
case **RawFeatureVector:
|
||||
f := NewRawFeatureVector()
|
||||
err = f.Decode(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*e = f
|
||||
|
||||
case *[]Sig:
|
||||
var l [2]byte
|
||||
if _, err := io.ReadFull(r, l[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
numSigs := binary.BigEndian.Uint16(l[:])
|
||||
|
||||
var sigs []Sig
|
||||
if numSigs > 0 {
|
||||
sigs = make([]Sig, numSigs)
|
||||
for i := 0; i < int(numSigs); i++ {
|
||||
if err := ReadElement(r, &sigs[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*e = sigs
|
||||
|
||||
case *Sig:
|
||||
if _, err := io.ReadFull(r, e[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case *OpaqueReason:
|
||||
var l [2]byte
|
||||
if _, err := io.ReadFull(r, l[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
reasonLen := binary.BigEndian.Uint16(l[:])
|
||||
|
||||
*e = OpaqueReason(make([]byte, reasonLen))
|
||||
if _, err := io.ReadFull(r, *e); err != nil {
|
||||
return err
|
||||
}
|
||||
case *ErrorData:
|
||||
var l [2]byte
|
||||
if _, err := io.ReadFull(r, l[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
errorLen := binary.BigEndian.Uint16(l[:])
|
||||
|
||||
*e = ErrorData(make([]byte, errorLen))
|
||||
if _, err := io.ReadFull(r, *e); err != nil {
|
||||
return err
|
||||
}
|
||||
case *PingPayload:
|
||||
var l [2]byte
|
||||
if _, err := io.ReadFull(r, l[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
pingLen := binary.BigEndian.Uint16(l[:])
|
||||
|
||||
*e = PingPayload(make([]byte, pingLen))
|
||||
if _, err := io.ReadFull(r, *e); err != nil {
|
||||
return err
|
||||
}
|
||||
case *PongPayload:
|
||||
var l [2]byte
|
||||
if _, err := io.ReadFull(r, l[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
pongLen := binary.BigEndian.Uint16(l[:])
|
||||
|
||||
*e = PongPayload(make([]byte, pongLen))
|
||||
if _, err := io.ReadFull(r, *e); err != nil {
|
||||
return err
|
||||
}
|
||||
case *[33]byte:
|
||||
if _, err := io.ReadFull(r, e[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
case []byte:
|
||||
if _, err := io.ReadFull(r, e); err != nil {
|
||||
return err
|
||||
}
|
||||
case *PkScript:
|
||||
pkScript, err := wire.ReadVarBytes(r, 0, 34, "pkscript")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*e = pkScript
|
||||
case *wire.OutPoint:
|
||||
var h [32]byte
|
||||
if _, err = io.ReadFull(r, h[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
hash, err := chainhash.NewHash(h[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var idxBytes [2]byte
|
||||
_, err = io.ReadFull(r, idxBytes[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
index := binary.BigEndian.Uint16(idxBytes[:])
|
||||
|
||||
*e = wire.OutPoint{
|
||||
Hash: *hash,
|
||||
Index: uint32(index),
|
||||
}
|
||||
case *FailCode:
|
||||
if err := ReadElement(r, (*uint16)(e)); err != nil {
|
||||
return err
|
||||
}
|
||||
case *ChannelID:
|
||||
if _, err := io.ReadFull(r, e[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case *ShortChannelID:
|
||||
var blockHeight [4]byte
|
||||
if _, err = io.ReadFull(r, blockHeight[1:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var txIndex [4]byte
|
||||
if _, err = io.ReadFull(r, txIndex[1:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var txPosition [2]byte
|
||||
if _, err = io.ReadFull(r, txPosition[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*e = ShortChannelID{
|
||||
BlockHeight: binary.BigEndian.Uint32(blockHeight[:]),
|
||||
TxIndex: binary.BigEndian.Uint32(txIndex[:]),
|
||||
TxPosition: binary.BigEndian.Uint16(txPosition[:]),
|
||||
}
|
||||
|
||||
case *[]net.Addr:
|
||||
// First, we'll read the number of total bytes that have been
|
||||
// used to encode the set of addresses.
|
||||
var numAddrsBytes [2]byte
|
||||
if _, err = io.ReadFull(r, numAddrsBytes[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
addrsLen := binary.BigEndian.Uint16(numAddrsBytes[:])
|
||||
|
||||
// With the number of addresses, read, we'll now pull in the
|
||||
// buffer of the encoded addresses into memory.
|
||||
addrs := make([]byte, addrsLen)
|
||||
if _, err := io.ReadFull(r, addrs[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
addrBuf := bytes.NewReader(addrs)
|
||||
|
||||
// Finally, we'll parse the remaining address payload in
|
||||
// series, using the first byte to denote how to decode the
|
||||
// address itself.
|
||||
var (
|
||||
addresses []net.Addr
|
||||
addrBytesRead uint16
|
||||
)
|
||||
|
||||
for addrBytesRead < addrsLen {
|
||||
var descriptor [1]byte
|
||||
if _, err = io.ReadFull(addrBuf, descriptor[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addrBytesRead++
|
||||
|
||||
var address net.Addr
|
||||
switch aType := addressType(descriptor[0]); aType {
|
||||
case noAddr:
|
||||
addrBytesRead += aType.AddrLen()
|
||||
continue
|
||||
|
||||
case tcp4Addr:
|
||||
var ip [4]byte
|
||||
if _, err := io.ReadFull(addrBuf, ip[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var port [2]byte
|
||||
if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
address = &net.TCPAddr{
|
||||
IP: net.IP(ip[:]),
|
||||
Port: int(binary.BigEndian.Uint16(port[:])),
|
||||
}
|
||||
addrBytesRead += aType.AddrLen()
|
||||
|
||||
case tcp6Addr:
|
||||
var ip [16]byte
|
||||
if _, err := io.ReadFull(addrBuf, ip[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var port [2]byte
|
||||
if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
address = &net.TCPAddr{
|
||||
IP: net.IP(ip[:]),
|
||||
Port: int(binary.BigEndian.Uint16(port[:])),
|
||||
}
|
||||
addrBytesRead += aType.AddrLen()
|
||||
|
||||
case v2OnionAddr:
|
||||
var h [tor.V2DecodedLen]byte
|
||||
if _, err := io.ReadFull(addrBuf, h[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var p [2]byte
|
||||
if _, err := io.ReadFull(addrBuf, p[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
onionService := tor.Base32Encoding.EncodeToString(h[:])
|
||||
onionService += tor.OnionSuffix
|
||||
port := int(binary.BigEndian.Uint16(p[:]))
|
||||
|
||||
address = &tor.OnionAddr{
|
||||
OnionService: onionService,
|
||||
Port: port,
|
||||
}
|
||||
addrBytesRead += aType.AddrLen()
|
||||
|
||||
case v3OnionAddr:
|
||||
var h [tor.V3DecodedLen]byte
|
||||
if _, err := io.ReadFull(addrBuf, h[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var p [2]byte
|
||||
if _, err := io.ReadFull(addrBuf, p[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
onionService := tor.Base32Encoding.EncodeToString(h[:])
|
||||
onionService += tor.OnionSuffix
|
||||
port := int(binary.BigEndian.Uint16(p[:]))
|
||||
|
||||
address = &tor.OnionAddr{
|
||||
OnionService: onionService,
|
||||
Port: port,
|
||||
}
|
||||
addrBytesRead += aType.AddrLen()
|
||||
|
||||
default:
|
||||
return &ErrUnknownAddrType{aType}
|
||||
}
|
||||
|
||||
addresses = append(addresses, address)
|
||||
}
|
||||
|
||||
*e = addresses
|
||||
case *color.RGBA:
|
||||
err := ReadElements(r,
|
||||
&e.R,
|
||||
&e.G,
|
||||
&e.B,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case *DeliveryAddress:
|
||||
var addrLen [2]byte
|
||||
if _, err = io.ReadFull(r, addrLen[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
length := binary.BigEndian.Uint16(addrLen[:])
|
||||
|
||||
var addrBytes [34]byte
|
||||
if length > 34 {
|
||||
return fmt.Errorf("Cannot read %d bytes into addrBytes", length)
|
||||
}
|
||||
if _, err = io.ReadFull(r, addrBytes[:length]); err != nil {
|
||||
return err
|
||||
}
|
||||
*e = addrBytes[:length]
|
||||
default:
|
||||
return fmt.Errorf("Unknown type in ReadElement: %T", e)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadElements deserializes a variable number of elements into the passed
|
||||
// io.Reader, with each element being deserialized according to the ReadElement
|
||||
// function.
|
||||
func ReadElements(r io.Reader, elements ...interface{}) error {
|
||||
for _, element := range elements {
|
||||
err := ReadElement(r, element)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
296
vendor/github.com/lightningnetwork/lnd/lnwire/message.go
generated
vendored
Normal file
296
vendor/github.com/lightningnetwork/lnd/lnwire/message.go
generated
vendored
Normal file
@@ -0,0 +1,296 @@
|
||||
// Copyright (c) 2013-2017 The btcsuite developers
|
||||
// Copyright (c) 2015-2016 The Decred developers
|
||||
// code derived from https://github .com/btcsuite/btcd/blob/master/wire/message.go
|
||||
// Copyright (C) 2015-2017 The Lightning Network Developers
|
||||
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// MaxMessagePayload is the maximum bytes a message can be regardless of other
|
||||
// individual limits imposed by messages themselves.
|
||||
const MaxMessagePayload = 65535 // 65KB
|
||||
|
||||
// MessageType is the unique 2 byte big-endian integer that indicates the type
|
||||
// of message on the wire. All messages have a very simple header which
|
||||
// consists simply of 2-byte message type. We omit a length field, and checksum
|
||||
// as the Lightning Protocol is intended to be encapsulated within a
|
||||
// confidential+authenticated cryptographic messaging protocol.
|
||||
type MessageType uint16
|
||||
|
||||
// The currently defined message types within this current version of the
|
||||
// Lightning protocol.
|
||||
const (
|
||||
MsgInit MessageType = 16
|
||||
MsgError = 17
|
||||
MsgPing = 18
|
||||
MsgPong = 19
|
||||
MsgOpenChannel = 32
|
||||
MsgAcceptChannel = 33
|
||||
MsgFundingCreated = 34
|
||||
MsgFundingSigned = 35
|
||||
MsgFundingLocked = 36
|
||||
MsgShutdown = 38
|
||||
MsgClosingSigned = 39
|
||||
MsgUpdateAddHTLC = 128
|
||||
MsgUpdateFulfillHTLC = 130
|
||||
MsgUpdateFailHTLC = 131
|
||||
MsgCommitSig = 132
|
||||
MsgRevokeAndAck = 133
|
||||
MsgUpdateFee = 134
|
||||
MsgUpdateFailMalformedHTLC = 135
|
||||
MsgChannelReestablish = 136
|
||||
MsgChannelAnnouncement = 256
|
||||
MsgNodeAnnouncement = 257
|
||||
MsgChannelUpdate = 258
|
||||
MsgAnnounceSignatures = 259
|
||||
MsgQueryShortChanIDs = 261
|
||||
MsgReplyShortChanIDsEnd = 262
|
||||
MsgQueryChannelRange = 263
|
||||
MsgReplyChannelRange = 264
|
||||
MsgGossipTimestampRange = 265
|
||||
)
|
||||
|
||||
// String return the string representation of message type.
|
||||
func (t MessageType) String() string {
|
||||
switch t {
|
||||
case MsgInit:
|
||||
return "Init"
|
||||
case MsgOpenChannel:
|
||||
return "MsgOpenChannel"
|
||||
case MsgAcceptChannel:
|
||||
return "MsgAcceptChannel"
|
||||
case MsgFundingCreated:
|
||||
return "MsgFundingCreated"
|
||||
case MsgFundingSigned:
|
||||
return "MsgFundingSigned"
|
||||
case MsgFundingLocked:
|
||||
return "FundingLocked"
|
||||
case MsgShutdown:
|
||||
return "Shutdown"
|
||||
case MsgClosingSigned:
|
||||
return "ClosingSigned"
|
||||
case MsgUpdateAddHTLC:
|
||||
return "UpdateAddHTLC"
|
||||
case MsgUpdateFailHTLC:
|
||||
return "UpdateFailHTLC"
|
||||
case MsgUpdateFulfillHTLC:
|
||||
return "UpdateFulfillHTLC"
|
||||
case MsgCommitSig:
|
||||
return "CommitSig"
|
||||
case MsgRevokeAndAck:
|
||||
return "RevokeAndAck"
|
||||
case MsgUpdateFailMalformedHTLC:
|
||||
return "UpdateFailMalformedHTLC"
|
||||
case MsgChannelReestablish:
|
||||
return "ChannelReestablish"
|
||||
case MsgError:
|
||||
return "Error"
|
||||
case MsgChannelAnnouncement:
|
||||
return "ChannelAnnouncement"
|
||||
case MsgChannelUpdate:
|
||||
return "ChannelUpdate"
|
||||
case MsgNodeAnnouncement:
|
||||
return "NodeAnnouncement"
|
||||
case MsgPing:
|
||||
return "Ping"
|
||||
case MsgAnnounceSignatures:
|
||||
return "AnnounceSignatures"
|
||||
case MsgPong:
|
||||
return "Pong"
|
||||
case MsgUpdateFee:
|
||||
return "UpdateFee"
|
||||
case MsgQueryShortChanIDs:
|
||||
return "QueryShortChanIDs"
|
||||
case MsgReplyShortChanIDsEnd:
|
||||
return "ReplyShortChanIDsEnd"
|
||||
case MsgQueryChannelRange:
|
||||
return "QueryChannelRange"
|
||||
case MsgReplyChannelRange:
|
||||
return "ReplyChannelRange"
|
||||
case MsgGossipTimestampRange:
|
||||
return "GossipTimestampRange"
|
||||
default:
|
||||
return "<unknown>"
|
||||
}
|
||||
}
|
||||
|
||||
// UnknownMessage is an implementation of the error interface that allows the
|
||||
// creation of an error in response to an unknown message.
|
||||
type UnknownMessage struct {
|
||||
messageType MessageType
|
||||
}
|
||||
|
||||
// Error returns a human readable string describing the error.
|
||||
//
|
||||
// This is part of the error interface.
|
||||
func (u *UnknownMessage) Error() string {
|
||||
return fmt.Sprintf("unable to parse message of unknown type: %v",
|
||||
u.messageType)
|
||||
}
|
||||
|
||||
// Serializable is an interface which defines a lightning wire serializable
|
||||
// object.
|
||||
type Serializable interface {
|
||||
// Decode reads the bytes stream and converts it to the object.
|
||||
Decode(io.Reader, uint32) error
|
||||
|
||||
// Encode converts object to the bytes stream and write it into the
|
||||
// writer.
|
||||
Encode(io.Writer, uint32) error
|
||||
}
|
||||
|
||||
// Message is an interface that defines a lightning wire protocol message. The
|
||||
// interface is general in order to allow implementing types full control over
|
||||
// the representation of its data.
|
||||
type Message interface {
|
||||
Serializable
|
||||
MsgType() MessageType
|
||||
MaxPayloadLength(uint32) uint32
|
||||
}
|
||||
|
||||
// makeEmptyMessage creates a new empty message of the proper concrete type
|
||||
// based on the passed message type.
|
||||
func makeEmptyMessage(msgType MessageType) (Message, error) {
|
||||
var msg Message
|
||||
|
||||
switch msgType {
|
||||
case MsgInit:
|
||||
msg = &Init{}
|
||||
case MsgOpenChannel:
|
||||
msg = &OpenChannel{}
|
||||
case MsgAcceptChannel:
|
||||
msg = &AcceptChannel{}
|
||||
case MsgFundingCreated:
|
||||
msg = &FundingCreated{}
|
||||
case MsgFundingSigned:
|
||||
msg = &FundingSigned{}
|
||||
case MsgFundingLocked:
|
||||
msg = &FundingLocked{}
|
||||
case MsgShutdown:
|
||||
msg = &Shutdown{}
|
||||
case MsgClosingSigned:
|
||||
msg = &ClosingSigned{}
|
||||
case MsgUpdateAddHTLC:
|
||||
msg = &UpdateAddHTLC{}
|
||||
case MsgUpdateFailHTLC:
|
||||
msg = &UpdateFailHTLC{}
|
||||
case MsgUpdateFulfillHTLC:
|
||||
msg = &UpdateFulfillHTLC{}
|
||||
case MsgCommitSig:
|
||||
msg = &CommitSig{}
|
||||
case MsgRevokeAndAck:
|
||||
msg = &RevokeAndAck{}
|
||||
case MsgUpdateFee:
|
||||
msg = &UpdateFee{}
|
||||
case MsgUpdateFailMalformedHTLC:
|
||||
msg = &UpdateFailMalformedHTLC{}
|
||||
case MsgChannelReestablish:
|
||||
msg = &ChannelReestablish{}
|
||||
case MsgError:
|
||||
msg = &Error{}
|
||||
case MsgChannelAnnouncement:
|
||||
msg = &ChannelAnnouncement{}
|
||||
case MsgChannelUpdate:
|
||||
msg = &ChannelUpdate{}
|
||||
case MsgNodeAnnouncement:
|
||||
msg = &NodeAnnouncement{}
|
||||
case MsgPing:
|
||||
msg = &Ping{}
|
||||
case MsgAnnounceSignatures:
|
||||
msg = &AnnounceSignatures{}
|
||||
case MsgPong:
|
||||
msg = &Pong{}
|
||||
case MsgQueryShortChanIDs:
|
||||
msg = &QueryShortChanIDs{}
|
||||
case MsgReplyShortChanIDsEnd:
|
||||
msg = &ReplyShortChanIDsEnd{}
|
||||
case MsgQueryChannelRange:
|
||||
msg = &QueryChannelRange{}
|
||||
case MsgReplyChannelRange:
|
||||
msg = &ReplyChannelRange{}
|
||||
case MsgGossipTimestampRange:
|
||||
msg = &GossipTimestampRange{}
|
||||
default:
|
||||
return nil, &UnknownMessage{msgType}
|
||||
}
|
||||
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
// WriteMessage writes a lightning Message to w including the necessary header
|
||||
// information and returns the number of bytes written.
|
||||
func WriteMessage(w io.Writer, msg Message, pver uint32) (int, error) {
|
||||
totalBytes := 0
|
||||
|
||||
// Encode the message payload itself into a temporary buffer.
|
||||
// TODO(roasbeef): create buffer pool
|
||||
var bw bytes.Buffer
|
||||
if err := msg.Encode(&bw, pver); err != nil {
|
||||
return totalBytes, err
|
||||
}
|
||||
payload := bw.Bytes()
|
||||
lenp := len(payload)
|
||||
|
||||
// Enforce maximum overall message payload.
|
||||
if lenp > MaxMessagePayload {
|
||||
return totalBytes, fmt.Errorf("message payload is too large - "+
|
||||
"encoded %d bytes, but maximum message payload is %d bytes",
|
||||
lenp, MaxMessagePayload)
|
||||
}
|
||||
|
||||
// Enforce maximum message payload on the message type.
|
||||
mpl := msg.MaxPayloadLength(pver)
|
||||
if uint32(lenp) > mpl {
|
||||
return totalBytes, fmt.Errorf("message payload is too large - "+
|
||||
"encoded %d bytes, but maximum message payload of "+
|
||||
"type %v is %d bytes", lenp, msg.MsgType(), mpl)
|
||||
}
|
||||
|
||||
// With the initial sanity checks complete, we'll now write out the
|
||||
// message type itself.
|
||||
var mType [2]byte
|
||||
binary.BigEndian.PutUint16(mType[:], uint16(msg.MsgType()))
|
||||
n, err := w.Write(mType[:])
|
||||
totalBytes += n
|
||||
if err != nil {
|
||||
return totalBytes, err
|
||||
}
|
||||
|
||||
// With the message type written, we'll now write out the raw payload
|
||||
// itself.
|
||||
n, err = w.Write(payload)
|
||||
totalBytes += n
|
||||
|
||||
return totalBytes, err
|
||||
}
|
||||
|
||||
// ReadMessage reads, validates, and parses the next Lightning message from r
|
||||
// for the provided protocol version.
|
||||
func ReadMessage(r io.Reader, pver uint32) (Message, error) {
|
||||
// First, we'll read out the first two bytes of the message so we can
|
||||
// create the proper empty message.
|
||||
var mType [2]byte
|
||||
if _, err := io.ReadFull(r, mType[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
msgType := MessageType(binary.BigEndian.Uint16(mType[:]))
|
||||
|
||||
// Now that we know the target message type, we can create the proper
|
||||
// empty message type and decode the message into it.
|
||||
msg, err := makeEmptyMessage(msgType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := msg.Decode(r, pver); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return msg, nil
|
||||
}
|
||||
45
vendor/github.com/lightningnetwork/lnd/lnwire/msat.go
generated
vendored
Normal file
45
vendor/github.com/lightningnetwork/lnd/lnwire/msat.go
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/btcsuite/btcutil"
|
||||
)
|
||||
|
||||
// mSatScale is a value that's used to scale satoshis to milli-satoshis, and
|
||||
// the other way around.
|
||||
const mSatScale uint64 = 1000
|
||||
|
||||
// MilliSatoshi are the native unit of the Lightning Network. A milli-satoshi
|
||||
// is simply 1/1000th of a satoshi. There are 1000 milli-satoshis in a single
|
||||
// satoshi. Within the network, all HTLC payments are denominated in
|
||||
// milli-satoshis. As milli-satoshis aren't deliverable on the native
|
||||
// blockchain, before settling to broadcasting, the values are rounded down to
|
||||
// the nearest satoshi.
|
||||
type MilliSatoshi uint64
|
||||
|
||||
// NewMSatFromSatoshis creates a new MilliSatoshi instance from a target amount
|
||||
// of satoshis.
|
||||
func NewMSatFromSatoshis(sat btcutil.Amount) MilliSatoshi {
|
||||
return MilliSatoshi(uint64(sat) * mSatScale)
|
||||
}
|
||||
|
||||
// ToBTC converts the target MilliSatoshi amount to its corresponding value
|
||||
// when expressed in BTC.
|
||||
func (m MilliSatoshi) ToBTC() float64 {
|
||||
sat := m.ToSatoshis()
|
||||
return sat.ToBTC()
|
||||
}
|
||||
|
||||
// ToSatoshis converts the target MilliSatoshi amount to satoshis. Simply, this
|
||||
// sheds a factor of 1000 from the mSAT amount in order to convert it to SAT.
|
||||
func (m MilliSatoshi) ToSatoshis() btcutil.Amount {
|
||||
return btcutil.Amount(uint64(m) / mSatScale)
|
||||
}
|
||||
|
||||
// String returns the string representation of the mSAT amount.
|
||||
func (m MilliSatoshi) String() string {
|
||||
return fmt.Sprintf("%v mSAT", uint64(m))
|
||||
}
|
||||
|
||||
// TODO(roasbeef): extend with arithmetic operations?
|
||||
54
vendor/github.com/lightningnetwork/lnd/lnwire/netaddress.go
generated
vendored
Normal file
54
vendor/github.com/lightningnetwork/lnd/lnwire/netaddress.go
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
)
|
||||
|
||||
// NetAddress represents information pertaining to the identity and network
|
||||
// reachability of a peer. Information stored includes the node's identity
|
||||
// public key for establishing a confidential+authenticated connection, the
|
||||
// service bits it supports, and a TCP address the node is reachable at.
|
||||
//
|
||||
// TODO(roasbeef): merge with LinkNode in some fashion
|
||||
type NetAddress struct {
|
||||
// IdentityKey is the long-term static public key for a node. This node is
|
||||
// used throughout the network as a node's identity key. It is used to
|
||||
// authenticate any data sent to the network on behalf of the node, and
|
||||
// additionally to establish a confidential+authenticated connection with
|
||||
// the node.
|
||||
IdentityKey *btcec.PublicKey
|
||||
|
||||
// Address is the IP address and port of the node. This is left
|
||||
// general so that multiple implementations can be used.
|
||||
Address net.Addr
|
||||
|
||||
// ChainNet is the Bitcoin network this node is associated with.
|
||||
// TODO(roasbeef): make a slice in the future for multi-chain
|
||||
ChainNet wire.BitcoinNet
|
||||
}
|
||||
|
||||
// A compile time assertion to ensure that NetAddress meets the net.Addr
|
||||
// interface.
|
||||
var _ net.Addr = (*NetAddress)(nil)
|
||||
|
||||
// String returns a human readable string describing the target NetAddress. The
|
||||
// current string format is: <pubkey>@host.
|
||||
//
|
||||
// This part of the net.Addr interface.
|
||||
func (n *NetAddress) String() string {
|
||||
// TODO(roasbeef): use base58?
|
||||
pubkey := n.IdentityKey.SerializeCompressed()
|
||||
|
||||
return fmt.Sprintf("%x@%v", pubkey, n.Address)
|
||||
}
|
||||
|
||||
// Network returns the name of the network this address is bound to.
|
||||
//
|
||||
// This part of the net.Addr interface.
|
||||
func (n *NetAddress) Network() string {
|
||||
return n.Address.Network()
|
||||
}
|
||||
205
vendor/github.com/lightningnetwork/lnd/lnwire/node_announcement.go
generated
vendored
Normal file
205
vendor/github.com/lightningnetwork/lnd/lnwire/node_announcement.go
generated
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"image/color"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
var (
|
||||
startPort uint16 = 1024
|
||||
endPort uint16 = 49151
|
||||
)
|
||||
|
||||
// ErrUnknownAddrType is an error returned if we encounter an unknown address type
|
||||
// when parsing addresses.
|
||||
type ErrUnknownAddrType struct {
|
||||
addrType addressType
|
||||
}
|
||||
|
||||
// Error returns a human readable string describing the error.
|
||||
//
|
||||
// NOTE: implements the error interface.
|
||||
func (e ErrUnknownAddrType) Error() string {
|
||||
return fmt.Sprintf("unknown address type: %v", e.addrType)
|
||||
}
|
||||
|
||||
// ErrInvalidNodeAlias is an error returned if a node alias we parse on the
|
||||
// wire is invalid, as in it has non UTF-8 characters.
|
||||
type ErrInvalidNodeAlias struct{}
|
||||
|
||||
// Error returns a human readable string describing the error.
|
||||
//
|
||||
// NOTE: implements the error interface.
|
||||
func (e ErrInvalidNodeAlias) Error() string {
|
||||
return "node alias has non-utf8 characters"
|
||||
}
|
||||
|
||||
// NodeAlias a hex encoded UTF-8 string that may be displayed as an alternative
|
||||
// to the node's ID. Notice that aliases are not unique and may be freely
|
||||
// chosen by the node operators.
|
||||
type NodeAlias [32]byte
|
||||
|
||||
// NewNodeAlias creates a new instance of a NodeAlias. Verification is
|
||||
// performed on the passed string to ensure it meets the alias requirements.
|
||||
func NewNodeAlias(s string) (NodeAlias, error) {
|
||||
var n NodeAlias
|
||||
|
||||
if len(s) > 32 {
|
||||
return n, fmt.Errorf("alias too large: max is %v, got %v", 32,
|
||||
len(s))
|
||||
}
|
||||
|
||||
if !utf8.ValidString(s) {
|
||||
return n, &ErrInvalidNodeAlias{}
|
||||
}
|
||||
|
||||
copy(n[:], []byte(s))
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// String returns a utf8 string representation of the alias bytes.
|
||||
func (n NodeAlias) String() string {
|
||||
// Trim trailing zero-bytes for presentation
|
||||
return string(bytes.Trim(n[:], "\x00"))
|
||||
}
|
||||
|
||||
// NodeAnnouncement message is used to announce the presence of a Lightning
|
||||
// node and also to signal that the node is accepting incoming connections.
|
||||
// Each NodeAnnouncement authenticating the advertised information within the
|
||||
// announcement via a signature using the advertised node pubkey.
|
||||
type NodeAnnouncement struct {
|
||||
// Signature is used to prove the ownership of node id.
|
||||
Signature Sig
|
||||
|
||||
// Features is the list of protocol features this node supports.
|
||||
Features *RawFeatureVector
|
||||
|
||||
// Timestamp allows ordering in the case of multiple announcements.
|
||||
Timestamp uint32
|
||||
|
||||
// NodeID is a public key which is used as node identification.
|
||||
NodeID [33]byte
|
||||
|
||||
// RGBColor is used to customize their node's appearance in maps and
|
||||
// graphs
|
||||
RGBColor color.RGBA
|
||||
|
||||
// Alias is used to customize their node's appearance in maps and
|
||||
// graphs
|
||||
Alias NodeAlias
|
||||
|
||||
// Address includes two specification fields: 'ipv6' and 'port' on
|
||||
// which the node is accepting incoming connections.
|
||||
Addresses []net.Addr
|
||||
|
||||
// ExtraOpaqueData is the set of data that was appended to this
|
||||
// message, some of which we may not actually know how to iterate or
|
||||
// parse. By holding onto this data, we ensure that we're able to
|
||||
// properly validate the set of signatures that cover these new fields,
|
||||
// and ensure we're able to make upgrades to the network in a forwards
|
||||
// compatible manner.
|
||||
ExtraOpaqueData []byte
|
||||
}
|
||||
|
||||
// UpdateNodeAnnAddrs is a functional option that allows updating the addresses
|
||||
// of the given node announcement.
|
||||
func UpdateNodeAnnAddrs(addrs []net.Addr) func(*NodeAnnouncement) {
|
||||
return func(nodeAnn *NodeAnnouncement) {
|
||||
nodeAnn.Addresses = addrs
|
||||
}
|
||||
}
|
||||
|
||||
// A compile time check to ensure NodeAnnouncement implements the
|
||||
// lnwire.Message interface.
|
||||
var _ Message = (*NodeAnnouncement)(nil)
|
||||
|
||||
// Decode deserializes a serialized NodeAnnouncement stored in the passed
|
||||
// io.Reader observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *NodeAnnouncement) Decode(r io.Reader, pver uint32) error {
|
||||
err := ReadElements(r,
|
||||
&a.Signature,
|
||||
&a.Features,
|
||||
&a.Timestamp,
|
||||
&a.NodeID,
|
||||
&a.RGBColor,
|
||||
&a.Alias,
|
||||
&a.Addresses,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Now that we've read out all the fields that we explicitly know of,
|
||||
// we'll collect the remainder into the ExtraOpaqueData field. If there
|
||||
// aren't any bytes, then we'll snip off the slice to avoid carrying
|
||||
// around excess capacity.
|
||||
a.ExtraOpaqueData, err = ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(a.ExtraOpaqueData) == 0 {
|
||||
a.ExtraOpaqueData = nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Encode serializes the target NodeAnnouncement into the passed io.Writer
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
func (a *NodeAnnouncement) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
a.Signature,
|
||||
a.Features,
|
||||
a.Timestamp,
|
||||
a.NodeID,
|
||||
a.RGBColor,
|
||||
a.Alias,
|
||||
a.Addresses,
|
||||
a.ExtraOpaqueData,
|
||||
)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
// wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *NodeAnnouncement) MsgType() MessageType {
|
||||
return MsgNodeAnnouncement
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload size for this message
|
||||
// observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *NodeAnnouncement) MaxPayloadLength(pver uint32) uint32 {
|
||||
return 65533
|
||||
}
|
||||
|
||||
// DataToSign returns the part of the message that should be signed.
|
||||
func (a *NodeAnnouncement) DataToSign() ([]byte, error) {
|
||||
|
||||
// We should not include the signatures itself.
|
||||
var w bytes.Buffer
|
||||
err := WriteElements(&w,
|
||||
a.Features,
|
||||
a.Timestamp,
|
||||
a.NodeID,
|
||||
a.RGBColor,
|
||||
a.Alias[:],
|
||||
a.Addresses,
|
||||
a.ExtraOpaqueData,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return w.Bytes(), nil
|
||||
}
|
||||
1292
vendor/github.com/lightningnetwork/lnd/lnwire/onion_error.go
generated
vendored
Normal file
1292
vendor/github.com/lightningnetwork/lnd/lnwire/onion_error.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
202
vendor/github.com/lightningnetwork/lnd/lnwire/open_channel.go
generated
vendored
Normal file
202
vendor/github.com/lightningnetwork/lnd/lnwire/open_channel.go
generated
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcutil"
|
||||
)
|
||||
|
||||
// FundingFlag represents the possible bit mask values for the ChannelFlags
|
||||
// field within the OpenChannel struct.
|
||||
type FundingFlag uint8
|
||||
|
||||
const (
|
||||
// FFAnnounceChannel is a FundingFlag that when set, indicates the
|
||||
// initiator of a funding flow wishes to announce the channel to the
|
||||
// greater network.
|
||||
FFAnnounceChannel FundingFlag = 1 << iota
|
||||
)
|
||||
|
||||
// OpenChannel is the message Alice sends to Bob if we should like to create a
|
||||
// channel with Bob where she's the sole provider of funds to the channel.
|
||||
// Single funder channels simplify the initial funding workflow, are supported
|
||||
// by nodes backed by SPV Bitcoin clients, and have a simpler security models
|
||||
// than dual funded channels.
|
||||
type OpenChannel struct {
|
||||
// ChainHash is the target chain that the initiator wishes to open a
|
||||
// channel within.
|
||||
ChainHash chainhash.Hash
|
||||
|
||||
// PendingChannelID serves to uniquely identify the future channel
|
||||
// created by the initiated single funder workflow.
|
||||
PendingChannelID [32]byte
|
||||
|
||||
// FundingAmount is the amount of satoshis that the initiator of the
|
||||
// channel wishes to use as the total capacity of the channel. The
|
||||
// initial balance of the funding will be this value minus the push
|
||||
// amount (if set).
|
||||
FundingAmount btcutil.Amount
|
||||
|
||||
// PushAmount is the value that the initiating party wishes to "push"
|
||||
// to the responding as part of the first commitment state. If the
|
||||
// responder accepts, then this will be their initial balance.
|
||||
PushAmount MilliSatoshi
|
||||
|
||||
// DustLimit is the specific dust limit the sender of this message
|
||||
// would like enforced on their version of the commitment transaction.
|
||||
// Any output below this value will be "trimmed" from the commitment
|
||||
// transaction, with the amount of the HTLC going to dust.
|
||||
DustLimit btcutil.Amount
|
||||
|
||||
// MaxValueInFlight represents the maximum amount of coins that can be
|
||||
// pending within the channel at any given time. If the amount of funds
|
||||
// in limbo exceeds this amount, then the channel will be failed.
|
||||
MaxValueInFlight MilliSatoshi
|
||||
|
||||
// ChannelReserve is the amount of BTC that the receiving party MUST
|
||||
// maintain a balance above at all times. This is a safety mechanism to
|
||||
// ensure that both sides always have skin in the game during the
|
||||
// channel's lifetime.
|
||||
ChannelReserve btcutil.Amount
|
||||
|
||||
// HtlcMinimum is the smallest HTLC that the sender of this message
|
||||
// will accept.
|
||||
HtlcMinimum MilliSatoshi
|
||||
|
||||
// FeePerKiloWeight is the initial fee rate that the initiator suggests
|
||||
// for both commitment transaction. This value is expressed in sat per
|
||||
// kilo-weight.
|
||||
//
|
||||
// TODO(halseth): make SatPerKWeight when fee estimation is in own
|
||||
// package. Currently this will cause an import cycle.
|
||||
FeePerKiloWeight uint32
|
||||
|
||||
// CsvDelay is the number of blocks to use for the relative time lock
|
||||
// in the pay-to-self output of both commitment transactions.
|
||||
CsvDelay uint16
|
||||
|
||||
// MaxAcceptedHTLCs is the total number of incoming HTLC's that the
|
||||
// sender of this channel will accept.
|
||||
MaxAcceptedHTLCs uint16
|
||||
|
||||
// FundingKey is the key that should be used on behalf of the sender
|
||||
// within the 2-of-2 multi-sig output that it contained within the
|
||||
// funding transaction.
|
||||
FundingKey *btcec.PublicKey
|
||||
|
||||
// RevocationPoint is the base revocation point for the sending party.
|
||||
// Any commitment transaction belonging to the receiver of this message
|
||||
// should use this key and their per-commitment point to derive the
|
||||
// revocation key for the commitment transaction.
|
||||
RevocationPoint *btcec.PublicKey
|
||||
|
||||
// PaymentPoint is the base payment point for the sending party. This
|
||||
// key should be combined with the per commitment point for a
|
||||
// particular commitment state in order to create the key that should
|
||||
// be used in any output that pays directly to the sending party, and
|
||||
// also within the HTLC covenant transactions.
|
||||
PaymentPoint *btcec.PublicKey
|
||||
|
||||
// DelayedPaymentPoint is the delay point for the sending party. This
|
||||
// key should be combined with the per commitment point to derive the
|
||||
// keys that are used in outputs of the sender's commitment transaction
|
||||
// where they claim funds.
|
||||
DelayedPaymentPoint *btcec.PublicKey
|
||||
|
||||
// HtlcPoint is the base point used to derive the set of keys for this
|
||||
// party that will be used within the HTLC public key scripts. This
|
||||
// value is combined with the receiver's revocation base point in order
|
||||
// to derive the keys that are used within HTLC scripts.
|
||||
HtlcPoint *btcec.PublicKey
|
||||
|
||||
// FirstCommitmentPoint is the first commitment point for the sending
|
||||
// party. This value should be combined with the receiver's revocation
|
||||
// base point in order to derive the revocation keys that are placed
|
||||
// within the commitment transaction of the sender.
|
||||
FirstCommitmentPoint *btcec.PublicKey
|
||||
|
||||
// ChannelFlags is a bit-field which allows the initiator of the
|
||||
// channel to specify further behavior surrounding the channel.
|
||||
// Currently, the least significant bit of this bit field indicates the
|
||||
// initiator of the channel wishes to advertise this channel publicly.
|
||||
ChannelFlags FundingFlag
|
||||
}
|
||||
|
||||
// A compile time check to ensure OpenChannel implements the lnwire.Message
|
||||
// interface.
|
||||
var _ Message = (*OpenChannel)(nil)
|
||||
|
||||
// Encode serializes the target OpenChannel into the passed io.Writer
|
||||
// implementation. Serialization will observe the rules defined by the passed
|
||||
// protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (o *OpenChannel) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
o.ChainHash[:],
|
||||
o.PendingChannelID[:],
|
||||
o.FundingAmount,
|
||||
o.PushAmount,
|
||||
o.DustLimit,
|
||||
o.MaxValueInFlight,
|
||||
o.ChannelReserve,
|
||||
o.HtlcMinimum,
|
||||
o.FeePerKiloWeight,
|
||||
o.CsvDelay,
|
||||
o.MaxAcceptedHTLCs,
|
||||
o.FundingKey,
|
||||
o.RevocationPoint,
|
||||
o.PaymentPoint,
|
||||
o.DelayedPaymentPoint,
|
||||
o.HtlcPoint,
|
||||
o.FirstCommitmentPoint,
|
||||
o.ChannelFlags,
|
||||
)
|
||||
}
|
||||
|
||||
// Decode deserializes the serialized OpenChannel stored in the passed
|
||||
// io.Reader into the target OpenChannel using the deserialization rules
|
||||
// defined by the passed protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (o *OpenChannel) Decode(r io.Reader, pver uint32) error {
|
||||
return ReadElements(r,
|
||||
o.ChainHash[:],
|
||||
o.PendingChannelID[:],
|
||||
&o.FundingAmount,
|
||||
&o.PushAmount,
|
||||
&o.DustLimit,
|
||||
&o.MaxValueInFlight,
|
||||
&o.ChannelReserve,
|
||||
&o.HtlcMinimum,
|
||||
&o.FeePerKiloWeight,
|
||||
&o.CsvDelay,
|
||||
&o.MaxAcceptedHTLCs,
|
||||
&o.FundingKey,
|
||||
&o.RevocationPoint,
|
||||
&o.PaymentPoint,
|
||||
&o.DelayedPaymentPoint,
|
||||
&o.HtlcPoint,
|
||||
&o.FirstCommitmentPoint,
|
||||
&o.ChannelFlags,
|
||||
)
|
||||
}
|
||||
|
||||
// MsgType returns the MessageType code which uniquely identifies this message
|
||||
// as an OpenChannel on the wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (o *OpenChannel) MsgType() MessageType {
|
||||
return MsgOpenChannel
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload length for a
|
||||
// OpenChannel message.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (o *OpenChannel) MaxPayloadLength(uint32) uint32 {
|
||||
// (32 * 2) + (8 * 6) + (4 * 1) + (2 * 2) + (33 * 6) + 1
|
||||
return 319
|
||||
}
|
||||
67
vendor/github.com/lightningnetwork/lnd/lnwire/ping.go
generated
vendored
Normal file
67
vendor/github.com/lightningnetwork/lnd/lnwire/ping.go
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
package lnwire
|
||||
|
||||
import "io"
|
||||
|
||||
// PingPayload is a set of opaque bytes used to pad out a ping message.
|
||||
type PingPayload []byte
|
||||
|
||||
// Ping defines a message which is sent by peers periodically to determine if
|
||||
// the connection is still valid. Each ping message carries the number of bytes
|
||||
// to pad the pong response with, and also a number of bytes to be ignored at
|
||||
// the end of the ping message (which is padding).
|
||||
type Ping struct {
|
||||
// NumPongBytes is the number of bytes the pong response to this
|
||||
// message should carry.
|
||||
NumPongBytes uint16
|
||||
|
||||
// PaddingBytes is a set of opaque bytes used to pad out this ping
|
||||
// message. Using this field in conjunction to the one above, it's
|
||||
// possible for node to generate fake cover traffic.
|
||||
PaddingBytes PingPayload
|
||||
}
|
||||
|
||||
// NewPing returns a new Ping message.
|
||||
func NewPing(numBytes uint16) *Ping {
|
||||
return &Ping{
|
||||
NumPongBytes: numBytes,
|
||||
}
|
||||
}
|
||||
|
||||
// A compile time check to ensure Ping implements the lnwire.Message interface.
|
||||
var _ Message = (*Ping)(nil)
|
||||
|
||||
// Decode deserializes a serialized Ping message stored in the passed io.Reader
|
||||
// observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (p *Ping) Decode(r io.Reader, pver uint32) error {
|
||||
return ReadElements(r,
|
||||
&p.NumPongBytes,
|
||||
&p.PaddingBytes)
|
||||
}
|
||||
|
||||
// Encode serializes the target Ping into the passed io.Writer observing the
|
||||
// protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (p *Ping) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
p.NumPongBytes,
|
||||
p.PaddingBytes)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
// wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (p *Ping) MsgType() MessageType {
|
||||
return MsgPing
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload size for a Ping
|
||||
// complete message observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (p Ping) MaxPayloadLength(uint32) uint32 {
|
||||
return 65532
|
||||
}
|
||||
63
vendor/github.com/lightningnetwork/lnd/lnwire/pong.go
generated
vendored
Normal file
63
vendor/github.com/lightningnetwork/lnd/lnwire/pong.go
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
package lnwire
|
||||
|
||||
import "io"
|
||||
|
||||
// PongPayload is a set of opaque bytes sent in response to a ping message.
|
||||
type PongPayload []byte
|
||||
|
||||
// Pong defines a message which is the direct response to a received Ping
|
||||
// message. A Pong reply indicates that a connection is still active. The Pong
|
||||
// reply to a Ping message should contain the nonce carried in the original
|
||||
// Pong message.
|
||||
type Pong struct {
|
||||
// PongBytes is a set of opaque bytes that corresponds to the
|
||||
// NumPongBytes defined in the ping message that this pong is
|
||||
// replying to.
|
||||
PongBytes PongPayload
|
||||
}
|
||||
|
||||
// NewPong returns a new Pong message.
|
||||
func NewPong(pongBytes []byte) *Pong {
|
||||
return &Pong{
|
||||
PongBytes: pongBytes,
|
||||
}
|
||||
}
|
||||
|
||||
// A compile time check to ensure Pong implements the lnwire.Message interface.
|
||||
var _ Message = (*Pong)(nil)
|
||||
|
||||
// Decode deserializes a serialized Pong message stored in the passed io.Reader
|
||||
// observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (p *Pong) Decode(r io.Reader, pver uint32) error {
|
||||
return ReadElements(r,
|
||||
&p.PongBytes,
|
||||
)
|
||||
}
|
||||
|
||||
// Encode serializes the target Pong into the passed io.Writer observing the
|
||||
// protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (p *Pong) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
p.PongBytes,
|
||||
)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
// wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (p *Pong) MsgType() MessageType {
|
||||
return MsgPong
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload size for a Pong
|
||||
// complete message observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (p *Pong) MaxPayloadLength(uint32) uint32 {
|
||||
return 65532
|
||||
}
|
||||
77
vendor/github.com/lightningnetwork/lnd/lnwire/query_channel_range.go
generated
vendored
Normal file
77
vendor/github.com/lightningnetwork/lnd/lnwire/query_channel_range.go
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
)
|
||||
|
||||
// QueryChannelRange is a message sent by a node in order to query the
|
||||
// receiving node of the set of open channel they know of with short channel
|
||||
// ID's after the specified block height, capped at the number of blocks beyond
|
||||
// that block height. This will be used by nodes upon initial connect to
|
||||
// synchronize their views of the network.
|
||||
type QueryChannelRange struct {
|
||||
// ChainHash denotes the target chain that we're trying to synchronize
|
||||
// channel graph state for.
|
||||
ChainHash chainhash.Hash
|
||||
|
||||
// FirstBlockHeight is the first block in the query range. The
|
||||
// responder should send all new short channel IDs from this block
|
||||
// until this block plus the specified number of blocks.
|
||||
FirstBlockHeight uint32
|
||||
|
||||
// NumBlocks is the number of blocks beyond the first block that short
|
||||
// channel ID's should be sent for.
|
||||
NumBlocks uint32
|
||||
}
|
||||
|
||||
// NewQueryChannelRange creates a new empty QueryChannelRange message.
|
||||
func NewQueryChannelRange() *QueryChannelRange {
|
||||
return &QueryChannelRange{}
|
||||
}
|
||||
|
||||
// A compile time check to ensure QueryChannelRange implements the
|
||||
// lnwire.Message interface.
|
||||
var _ Message = (*QueryChannelRange)(nil)
|
||||
|
||||
// Decode deserializes a serialized QueryChannelRange message stored in the
|
||||
// passed io.Reader observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (q *QueryChannelRange) Decode(r io.Reader, pver uint32) error {
|
||||
return ReadElements(r,
|
||||
q.ChainHash[:],
|
||||
&q.FirstBlockHeight,
|
||||
&q.NumBlocks,
|
||||
)
|
||||
}
|
||||
|
||||
// Encode serializes the target QueryChannelRange into the passed io.Writer
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (q *QueryChannelRange) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
q.ChainHash[:],
|
||||
q.FirstBlockHeight,
|
||||
q.NumBlocks,
|
||||
)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
// wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (q *QueryChannelRange) MsgType() MessageType {
|
||||
return MsgQueryChannelRange
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload size for a
|
||||
// QueryChannelRange complete message observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (q *QueryChannelRange) MaxPayloadLength(uint32) uint32 {
|
||||
// 32 + 4 + 4
|
||||
return 40
|
||||
}
|
||||
371
vendor/github.com/lightningnetwork/lnd/lnwire/query_short_chan_ids.go
generated
vendored
Normal file
371
vendor/github.com/lightningnetwork/lnd/lnwire/query_short_chan_ids.go
generated
vendored
Normal file
@@ -0,0 +1,371 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/zlib"
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
)
|
||||
|
||||
// ShortChanIDEncoding is an enum-like type that represents exactly how a set
|
||||
// of short channel ID's is encoded on the wire. The set of encodings allows us
|
||||
// to take advantage of the structure of a list of short channel ID's to
|
||||
// achieving a high degree of compression.
|
||||
type ShortChanIDEncoding uint8
|
||||
|
||||
const (
|
||||
// EncodingSortedPlain signals that the set of short channel ID's is
|
||||
// encoded using the regular encoding, in a sorted order.
|
||||
EncodingSortedPlain ShortChanIDEncoding = 0
|
||||
|
||||
// EncodingSortedZlib signals that the set of short channel ID's is
|
||||
// encoded by first sorting the set of channel ID's, as then
|
||||
// compressing them using zlib.
|
||||
EncodingSortedZlib ShortChanIDEncoding = 1
|
||||
)
|
||||
|
||||
const (
|
||||
// maxZlibBufSize is the max number of bytes that we'll accept from a
|
||||
// zlib decoding instance. We do this in order to limit the total
|
||||
// amount of memory allocated during a decoding instance.
|
||||
maxZlibBufSize = 67413630
|
||||
)
|
||||
|
||||
// zlibDecodeMtx is a package level mutex that we'll use in order to ensure
|
||||
// that we'll only attempt a single zlib decoding instance at a time. This
|
||||
// allows us to also further bound our memory usage.
|
||||
var zlibDecodeMtx sync.Mutex
|
||||
|
||||
// ErrUnknownShortChanIDEncoding is a parametrized error that indicates that we
|
||||
// came across an unknown short channel ID encoding, and therefore were unable
|
||||
// to continue parsing.
|
||||
func ErrUnknownShortChanIDEncoding(encoding ShortChanIDEncoding) error {
|
||||
return fmt.Errorf("unknown short chan id encoding: %v", encoding)
|
||||
}
|
||||
|
||||
// QueryShortChanIDs is a message that allows the sender to query a set of
|
||||
// channel announcement and channel update messages that correspond to the set
|
||||
// of encoded short channel ID's. The encoding of the short channel ID's is
|
||||
// detailed in the query message ensuring that the receiver knows how to
|
||||
// properly decode each encode short channel ID which may be encoded using a
|
||||
// compression format. The receiver should respond with a series of channel
|
||||
// announcement and channel updates, finally sending a ReplyShortChanIDsEnd
|
||||
// message.
|
||||
type QueryShortChanIDs struct {
|
||||
// ChainHash denotes the target chain that we're querying for the
|
||||
// channel channel ID's of.
|
||||
ChainHash chainhash.Hash
|
||||
|
||||
// EncodingType is a signal to the receiver of the message that
|
||||
// indicates exactly how the set of short channel ID's that follow have
|
||||
// been encoded.
|
||||
EncodingType ShortChanIDEncoding
|
||||
|
||||
// ShortChanIDs is a slice of decoded short channel ID's.
|
||||
ShortChanIDs []ShortChannelID
|
||||
}
|
||||
|
||||
// NewQueryShortChanIDs creates a new QueryShortChanIDs message.
|
||||
func NewQueryShortChanIDs(h chainhash.Hash, e ShortChanIDEncoding,
|
||||
s []ShortChannelID) *QueryShortChanIDs {
|
||||
|
||||
return &QueryShortChanIDs{
|
||||
ChainHash: h,
|
||||
EncodingType: e,
|
||||
ShortChanIDs: s,
|
||||
}
|
||||
}
|
||||
|
||||
// A compile time check to ensure QueryShortChanIDs implements the
|
||||
// lnwire.Message interface.
|
||||
var _ Message = (*QueryShortChanIDs)(nil)
|
||||
|
||||
// Decode deserializes a serialized QueryShortChanIDs message stored in the
|
||||
// passed io.Reader observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (q *QueryShortChanIDs) Decode(r io.Reader, pver uint32) error {
|
||||
err := ReadElements(r, q.ChainHash[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
q.EncodingType, q.ShortChanIDs, err = decodeShortChanIDs(r)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// decodeShortChanIDs decodes a set of short channel ID's that have been
|
||||
// encoded. The first byte of the body details how the short chan ID's were
|
||||
// encoded. We'll use this type to govern exactly how we go about encoding the
|
||||
// set of short channel ID's.
|
||||
func decodeShortChanIDs(r io.Reader) (ShortChanIDEncoding, []ShortChannelID, error) {
|
||||
// First, we'll attempt to read the number of bytes in the body of the
|
||||
// set of encoded short channel ID's.
|
||||
var numBytesResp uint16
|
||||
err := ReadElements(r, &numBytesResp)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
if numBytesResp == 0 {
|
||||
return 0, nil, fmt.Errorf("No encoding type specified")
|
||||
}
|
||||
|
||||
queryBody := make([]byte, numBytesResp)
|
||||
if _, err := io.ReadFull(r, queryBody); err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
// The first byte is the encoding type, so we'll extract that so we can
|
||||
// continue our parsing.
|
||||
encodingType := ShortChanIDEncoding(queryBody[0])
|
||||
|
||||
// Before continuing, we'll snip off the first byte of the query body
|
||||
// as that was just the encoding type.
|
||||
queryBody = queryBody[1:]
|
||||
|
||||
// Otherwise, depending on the encoding type, we'll decode the encode
|
||||
// short channel ID's in a different manner.
|
||||
switch encodingType {
|
||||
|
||||
// In this encoding, we'll simply read a sort array of encoded short
|
||||
// channel ID's from the buffer.
|
||||
case EncodingSortedPlain:
|
||||
// If after extracting the encoding type, then number of
|
||||
// remaining bytes instead a whole multiple of the size of an
|
||||
// encoded short channel ID (8 bytes), then we'll return a
|
||||
// parsing error.
|
||||
if len(queryBody)%8 != 0 {
|
||||
return 0, nil, fmt.Errorf("whole number of short "+
|
||||
"chan ID's cannot be encoded in len=%v",
|
||||
len(queryBody))
|
||||
}
|
||||
|
||||
// As each short channel ID is encoded as 8 bytes, we can
|
||||
// compute the number of bytes encoded based on the size of the
|
||||
// query body.
|
||||
numShortChanIDs := len(queryBody) / 8
|
||||
if numShortChanIDs == 0 {
|
||||
return encodingType, nil, nil
|
||||
}
|
||||
|
||||
// Finally, we'll read out the exact number of short channel
|
||||
// ID's to conclude our parsing.
|
||||
shortChanIDs := make([]ShortChannelID, numShortChanIDs)
|
||||
bodyReader := bytes.NewReader(queryBody)
|
||||
for i := 0; i < numShortChanIDs; i++ {
|
||||
if err := ReadElements(bodyReader, &shortChanIDs[i]); err != nil {
|
||||
return 0, nil, fmt.Errorf("unable to parse "+
|
||||
"short chan ID: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return encodingType, shortChanIDs, nil
|
||||
|
||||
// In this encoding, we'll use zlib to decode the compressed payload.
|
||||
// However, we'll pay attention to ensure that we don't open our selves
|
||||
// up to a memory exhaustion attack.
|
||||
case EncodingSortedZlib:
|
||||
// We'll obtain an ultimately release the zlib decode mutex.
|
||||
// This guards us against allocating too much memory to decode
|
||||
// each instance from concurrent peers.
|
||||
zlibDecodeMtx.Lock()
|
||||
defer zlibDecodeMtx.Unlock()
|
||||
|
||||
// Before we start to decode, we'll create a limit reader over
|
||||
// the current reader. This will ensure that we can control how
|
||||
// much memory we're allocating during the decoding process.
|
||||
limitedDecompressor, err := zlib.NewReader(&io.LimitedReader{
|
||||
R: bytes.NewReader(queryBody),
|
||||
N: maxZlibBufSize,
|
||||
})
|
||||
if err != nil {
|
||||
return 0, nil, fmt.Errorf("unable to create zlib reader: %v", err)
|
||||
}
|
||||
|
||||
var (
|
||||
shortChanIDs []ShortChannelID
|
||||
lastChanID ShortChannelID
|
||||
)
|
||||
for {
|
||||
// We'll now attempt to read the next short channel ID
|
||||
// encoded in the payload.
|
||||
var cid ShortChannelID
|
||||
err := ReadElements(limitedDecompressor, &cid)
|
||||
|
||||
switch {
|
||||
// If we get an EOF error, then that either means we've
|
||||
// read all that's contained in the buffer, or have hit
|
||||
// our limit on the number of bytes we'll read. In
|
||||
// either case, we'll return what we have so far.
|
||||
case err == io.ErrUnexpectedEOF || err == io.EOF:
|
||||
return encodingType, shortChanIDs, nil
|
||||
|
||||
// Otherwise, we hit some other sort of error, possibly
|
||||
// an invalid payload, so we'll exit early with the
|
||||
// error.
|
||||
case err != nil:
|
||||
return 0, nil, fmt.Errorf("unable to "+
|
||||
"deflate next short chan "+
|
||||
"ID: %v", err)
|
||||
}
|
||||
|
||||
// We successfully read the next ID, so well collect
|
||||
// that in the set of final ID's to return.
|
||||
shortChanIDs = append(shortChanIDs, cid)
|
||||
|
||||
// Finally, we'll ensure that this short chan ID is
|
||||
// greater than the last one. This is a requirement
|
||||
// within the encoding, and if violated can aide us in
|
||||
// detecting malicious payloads.
|
||||
if cid.ToUint64() <= lastChanID.ToUint64() {
|
||||
return 0, nil, fmt.Errorf("current sid of %v "+
|
||||
"isn't greater than last sid of %v", cid,
|
||||
lastChanID)
|
||||
}
|
||||
|
||||
lastChanID = cid
|
||||
}
|
||||
|
||||
default:
|
||||
// If we've been sent an encoding type that we don't know of,
|
||||
// then we'll return a parsing error as we can't continue if
|
||||
// we're unable to encode them.
|
||||
return 0, nil, ErrUnknownShortChanIDEncoding(encodingType)
|
||||
}
|
||||
}
|
||||
|
||||
// Encode serializes the target QueryShortChanIDs into the passed io.Writer
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (q *QueryShortChanIDs) Encode(w io.Writer, pver uint32) error {
|
||||
// First, we'll write out the chain hash.
|
||||
err := WriteElements(w, q.ChainHash[:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Base on our encoding type, we'll write out the set of short channel
|
||||
// ID's.
|
||||
return encodeShortChanIDs(w, q.EncodingType, q.ShortChanIDs)
|
||||
}
|
||||
|
||||
// encodeShortChanIDs encodes the passed short channel ID's into the passed
|
||||
// io.Writer, respecting the specified encoding type.
|
||||
func encodeShortChanIDs(w io.Writer, encodingType ShortChanIDEncoding,
|
||||
shortChanIDs []ShortChannelID) error {
|
||||
|
||||
// For both of the current encoding types, the channel ID's are to be
|
||||
// sorted in place, so we'll do that now.
|
||||
sort.Slice(shortChanIDs, func(i, j int) bool {
|
||||
return shortChanIDs[i].ToUint64() <
|
||||
shortChanIDs[j].ToUint64()
|
||||
})
|
||||
|
||||
switch encodingType {
|
||||
|
||||
// In this encoding, we'll simply write a sorted array of encoded short
|
||||
// channel ID's from the buffer.
|
||||
case EncodingSortedPlain:
|
||||
// First, we'll write out the number of bytes of the query
|
||||
// body. We add 1 as the response will have the encoding type
|
||||
// prepended to it.
|
||||
numBytesBody := uint16(len(shortChanIDs)*8) + 1
|
||||
if err := WriteElements(w, numBytesBody); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// We'll then write out the encoding that that follows the
|
||||
// actual encoded short channel ID's.
|
||||
if err := WriteElements(w, encodingType); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Now that we know they're sorted, we can write out each short
|
||||
// channel ID to the buffer.
|
||||
for _, chanID := range shortChanIDs {
|
||||
if err := WriteElements(w, chanID); err != nil {
|
||||
return fmt.Errorf("unable to write short chan "+
|
||||
"ID: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
// For this encoding we'll first write out a serialized version of all
|
||||
// the channel ID's into a buffer, then zlib encode that. The final
|
||||
// payload is what we'll write out to the passed io.Writer.
|
||||
//
|
||||
// TODO(roasbeef): assumes the caller knows the proper chunk size to
|
||||
// pass to avoid bin-packing here
|
||||
case EncodingSortedZlib:
|
||||
// We'll make a new buffer, then wrap that with a zlib writer
|
||||
// so we can write directly to the buffer and encode in a
|
||||
// streaming manner.
|
||||
var buf bytes.Buffer
|
||||
zlibWriter := zlib.NewWriter(&buf)
|
||||
|
||||
// Next, we'll write out all the channel ID's directly into the
|
||||
// zlib writer, which will do compressing on the fly.
|
||||
for _, chanID := range shortChanIDs {
|
||||
err := WriteElements(zlibWriter, chanID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to write short chan "+
|
||||
"ID: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we've written all the elements, we'll ensure the
|
||||
// compressed stream is written to the underlying buffer.
|
||||
if err := zlibWriter.Close(); err != nil {
|
||||
return fmt.Errorf("unable to finalize "+
|
||||
"compression: %v", err)
|
||||
}
|
||||
|
||||
// Now that we have all the items compressed, we can compute
|
||||
// what the total payload size will be. We add one to account
|
||||
// for the byte to encode the type.
|
||||
compressedPayload := buf.Bytes()
|
||||
numBytesBody := len(compressedPayload) + 1
|
||||
|
||||
// Finally, we can write out the number of bytes, the
|
||||
// compression type, and finally the buffer itself.
|
||||
if err := WriteElements(w, uint16(numBytesBody)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := WriteElements(w, encodingType); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err := w.Write(compressedPayload)
|
||||
return err
|
||||
|
||||
default:
|
||||
// If we're trying to encode with an encoding type that we
|
||||
// don't know of, then we'll return a parsing error as we can't
|
||||
// continue if we're unable to encode them.
|
||||
return ErrUnknownShortChanIDEncoding(encodingType)
|
||||
}
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
// wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (q *QueryShortChanIDs) MsgType() MessageType {
|
||||
return MsgQueryShortChanIDs
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload size for a
|
||||
// QueryShortChanIDs complete message observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (q *QueryShortChanIDs) MaxPayloadLength(uint32) uint32 {
|
||||
return MaxMessagePayload
|
||||
}
|
||||
84
vendor/github.com/lightningnetwork/lnd/lnwire/reply_channel_range.go
generated
vendored
Normal file
84
vendor/github.com/lightningnetwork/lnd/lnwire/reply_channel_range.go
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
package lnwire
|
||||
|
||||
import "io"
|
||||
|
||||
// ReplyChannelRange is the response to the QueryChannelRange message. It
|
||||
// includes the original query, and the next streaming chunk of encoded short
|
||||
// channel ID's as the response. We'll also include a byte that indicates if
|
||||
// this is the last query in the message.
|
||||
type ReplyChannelRange struct {
|
||||
// QueryChannelRange is the corresponding query to this response.
|
||||
QueryChannelRange
|
||||
|
||||
// Complete denotes if this is the conclusion of the set of streaming
|
||||
// responses to the original query.
|
||||
Complete uint8
|
||||
|
||||
// EncodingType is a signal to the receiver of the message that
|
||||
// indicates exactly how the set of short channel ID's that follow have
|
||||
// been encoded.
|
||||
EncodingType ShortChanIDEncoding
|
||||
|
||||
// ShortChanIDs is a slice of decoded short channel ID's.
|
||||
ShortChanIDs []ShortChannelID
|
||||
}
|
||||
|
||||
// NewReplyChannelRange creates a new empty ReplyChannelRange message.
|
||||
func NewReplyChannelRange() *ReplyChannelRange {
|
||||
return &ReplyChannelRange{}
|
||||
}
|
||||
|
||||
// A compile time check to ensure ReplyChannelRange implements the
|
||||
// lnwire.Message interface.
|
||||
var _ Message = (*ReplyChannelRange)(nil)
|
||||
|
||||
// Decode deserializes a serialized ReplyChannelRange message stored in the
|
||||
// passed io.Reader observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *ReplyChannelRange) Decode(r io.Reader, pver uint32) error {
|
||||
err := c.QueryChannelRange.Decode(r, pver)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := ReadElements(r, &c.Complete); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.EncodingType, c.ShortChanIDs, err = decodeShortChanIDs(r)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Encode serializes the target ReplyChannelRange into the passed io.Writer
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *ReplyChannelRange) Encode(w io.Writer, pver uint32) error {
|
||||
if err := c.QueryChannelRange.Encode(w, pver); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteElements(w, c.Complete); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return encodeShortChanIDs(w, c.EncodingType, c.ShortChanIDs)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
// wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *ReplyChannelRange) MsgType() MessageType {
|
||||
return MsgReplyChannelRange
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload size for a
|
||||
// ReplyChannelRange complete message observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *ReplyChannelRange) MaxPayloadLength(uint32) uint32 {
|
||||
return MaxMessagePayload
|
||||
}
|
||||
74
vendor/github.com/lightningnetwork/lnd/lnwire/reply_short_chan_ids_end.go
generated
vendored
Normal file
74
vendor/github.com/lightningnetwork/lnd/lnwire/reply_short_chan_ids_end.go
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
)
|
||||
|
||||
// ReplyShortChanIDsEnd is a message that marks the end of a streaming message
|
||||
// response to an initial QueryShortChanIDs message. This marks that the
|
||||
// receiver of the original QueryShortChanIDs for the target chain has either
|
||||
// sent all adequate responses it knows of, or doesn't now of any short chan
|
||||
// ID's for the target chain.
|
||||
type ReplyShortChanIDsEnd struct {
|
||||
// ChainHash denotes the target chain that we're respond to a short
|
||||
// chan ID query for.
|
||||
ChainHash chainhash.Hash
|
||||
|
||||
// Complete will be set to 0 if we don't know of the chain that the
|
||||
// remote peer sent their query for. Otherwise, we'll set this to 1 in
|
||||
// order to indicate that we've sent all known responses for the prior
|
||||
// set of short chan ID's in the corresponding QueryShortChanIDs
|
||||
// message.
|
||||
Complete uint8
|
||||
}
|
||||
|
||||
// NewReplyShortChanIDsEnd creates a new empty ReplyShortChanIDsEnd message.
|
||||
func NewReplyShortChanIDsEnd() *ReplyShortChanIDsEnd {
|
||||
return &ReplyShortChanIDsEnd{}
|
||||
}
|
||||
|
||||
// A compile time check to ensure ReplyShortChanIDsEnd implements the
|
||||
// lnwire.Message interface.
|
||||
var _ Message = (*ReplyShortChanIDsEnd)(nil)
|
||||
|
||||
// Decode deserializes a serialized ReplyShortChanIDsEnd message stored in the
|
||||
// passed io.Reader observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *ReplyShortChanIDsEnd) Decode(r io.Reader, pver uint32) error {
|
||||
return ReadElements(r,
|
||||
c.ChainHash[:],
|
||||
&c.Complete,
|
||||
)
|
||||
}
|
||||
|
||||
// Encode serializes the target ReplyShortChanIDsEnd into the passed io.Writer
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *ReplyShortChanIDsEnd) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
c.ChainHash[:],
|
||||
c.Complete,
|
||||
)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
// wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *ReplyShortChanIDsEnd) MsgType() MessageType {
|
||||
return MsgReplyShortChanIDsEnd
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload size for a
|
||||
// ReplyShortChanIDsEnd complete message observing the specified protocol
|
||||
// version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *ReplyShortChanIDsEnd) MaxPayloadLength(uint32) uint32 {
|
||||
// 32 (chain hash) + 1 (complete)
|
||||
return 33
|
||||
}
|
||||
83
vendor/github.com/lightningnetwork/lnd/lnwire/revoke_and_ack.go
generated
vendored
Normal file
83
vendor/github.com/lightningnetwork/lnd/lnwire/revoke_and_ack.go
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
)
|
||||
|
||||
// RevokeAndAck is sent by either side once a CommitSig message has been
|
||||
// received, and validated. This message serves to revoke the prior commitment
|
||||
// transaction, which was the most up to date version until a CommitSig message
|
||||
// referencing the specified ChannelPoint was received. Additionally, this
|
||||
// message also piggyback's the next revocation hash that Alice should use when
|
||||
// constructing the Bob's version of the next commitment transaction (which
|
||||
// would be done before sending a CommitSig message). This piggybacking allows
|
||||
// Alice to send the next CommitSig message modifying Bob's commitment
|
||||
// transaction without first asking for a revocation hash initially.
|
||||
type RevokeAndAck struct {
|
||||
// ChanID uniquely identifies to which currently active channel this
|
||||
// RevokeAndAck applies to.
|
||||
ChanID ChannelID
|
||||
|
||||
// Revocation is the preimage to the revocation hash of the now prior
|
||||
// commitment transaction.
|
||||
Revocation [32]byte
|
||||
|
||||
// NextRevocationKey is the next commitment point which should be used
|
||||
// for the next commitment transaction the remote peer creates for us.
|
||||
// This, in conjunction without revocation base point will be used to
|
||||
// create the proper revocation key used within the commitment
|
||||
// transaction.
|
||||
NextRevocationKey *btcec.PublicKey
|
||||
}
|
||||
|
||||
// NewRevokeAndAck creates a new RevokeAndAck message.
|
||||
func NewRevokeAndAck() *RevokeAndAck {
|
||||
return &RevokeAndAck{}
|
||||
}
|
||||
|
||||
// A compile time check to ensure RevokeAndAck implements the lnwire.Message
|
||||
// interface.
|
||||
var _ Message = (*RevokeAndAck)(nil)
|
||||
|
||||
// Decode deserializes a serialized RevokeAndAck message stored in the
|
||||
// passed io.Reader observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *RevokeAndAck) Decode(r io.Reader, pver uint32) error {
|
||||
return ReadElements(r,
|
||||
&c.ChanID,
|
||||
c.Revocation[:],
|
||||
&c.NextRevocationKey,
|
||||
)
|
||||
}
|
||||
|
||||
// Encode serializes the target RevokeAndAck into the passed io.Writer
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *RevokeAndAck) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
c.ChanID,
|
||||
c.Revocation[:],
|
||||
c.NextRevocationKey,
|
||||
)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
// wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *RevokeAndAck) MsgType() MessageType {
|
||||
return MsgRevokeAndAck
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload size for a RevokeAndAck
|
||||
// complete message observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *RevokeAndAck) MaxPayloadLength(uint32) uint32 {
|
||||
// 32 + 32 + 33
|
||||
return 97
|
||||
}
|
||||
48
vendor/github.com/lightningnetwork/lnd/lnwire/short_channel_id.go
generated
vendored
Normal file
48
vendor/github.com/lightningnetwork/lnd/lnwire/short_channel_id.go
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// ShortChannelID represents the set of data which is needed to retrieve all
|
||||
// necessary data to validate the channel existence.
|
||||
type ShortChannelID struct {
|
||||
// BlockHeight is the height of the block where funding transaction
|
||||
// located.
|
||||
//
|
||||
// NOTE: This field is limited to 3 bytes.
|
||||
BlockHeight uint32
|
||||
|
||||
// TxIndex is a position of funding transaction within a block.
|
||||
//
|
||||
// NOTE: This field is limited to 3 bytes.
|
||||
TxIndex uint32
|
||||
|
||||
// TxPosition indicating transaction output which pays to the channel.
|
||||
TxPosition uint16
|
||||
}
|
||||
|
||||
// NewShortChanIDFromInt returns a new ShortChannelID which is the decoded
|
||||
// version of the compact channel ID encoded within the uint64. The format of
|
||||
// the compact channel ID is as follows: 3 bytes for the block height, 3 bytes
|
||||
// for the transaction index, and 2 bytes for the output index.
|
||||
func NewShortChanIDFromInt(chanID uint64) ShortChannelID {
|
||||
return ShortChannelID{
|
||||
BlockHeight: uint32(chanID >> 40),
|
||||
TxIndex: uint32(chanID>>16) & 0xFFFFFF,
|
||||
TxPosition: uint16(chanID),
|
||||
}
|
||||
}
|
||||
|
||||
// ToUint64 converts the ShortChannelID into a compact format encoded within a
|
||||
// uint64 (8 bytes).
|
||||
func (c ShortChannelID) ToUint64() uint64 {
|
||||
// TODO(roasbeef): explicit error on overflow?
|
||||
return ((uint64(c.BlockHeight) << 40) | (uint64(c.TxIndex) << 16) |
|
||||
(uint64(c.TxPosition)))
|
||||
}
|
||||
|
||||
// String generates a human-readable representation of the channel ID.
|
||||
func (c ShortChannelID) String() string {
|
||||
return fmt.Sprintf("%d:%d:%d", c.BlockHeight, c.TxIndex, c.TxPosition)
|
||||
}
|
||||
81
vendor/github.com/lightningnetwork/lnd/lnwire/shutdown.go
generated
vendored
Normal file
81
vendor/github.com/lightningnetwork/lnd/lnwire/shutdown.go
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// Shutdown is sent by either side in order to initiate the cooperative closure
|
||||
// of a channel. This message is sparse as both sides implicitly have the
|
||||
// information necessary to construct a transaction that will send the settled
|
||||
// funds of both parties to the final delivery addresses negotiated during the
|
||||
// funding workflow.
|
||||
type Shutdown struct {
|
||||
// ChannelID serves to identify which channel is to be closed.
|
||||
ChannelID ChannelID
|
||||
|
||||
// Address is the script to which the channel funds will be paid.
|
||||
Address DeliveryAddress
|
||||
}
|
||||
|
||||
// DeliveryAddress is used to communicate the address to which funds from a
|
||||
// closed channel should be sent. The address can be a p2wsh, p2pkh, p2sh or
|
||||
// p2wpkh.
|
||||
type DeliveryAddress []byte
|
||||
|
||||
// NewShutdown creates a new Shutdown message.
|
||||
func NewShutdown(cid ChannelID, addr DeliveryAddress) *Shutdown {
|
||||
return &Shutdown{
|
||||
ChannelID: cid,
|
||||
Address: addr,
|
||||
}
|
||||
}
|
||||
|
||||
// A compile-time check to ensure Shutdown implements the lnwire.Message
|
||||
// interface.
|
||||
var _ Message = (*Shutdown)(nil)
|
||||
|
||||
// Decode deserializes a serialized Shutdown stored in the passed io.Reader
|
||||
// observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (s *Shutdown) Decode(r io.Reader, pver uint32) error {
|
||||
return ReadElements(r, &s.ChannelID, &s.Address)
|
||||
}
|
||||
|
||||
// Encode serializes the target Shutdown into the passed io.Writer observing
|
||||
// the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (s *Shutdown) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w, s.ChannelID, s.Address)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
// wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (s *Shutdown) MsgType() MessageType {
|
||||
return MsgShutdown
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload size for this message
|
||||
// observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (s *Shutdown) MaxPayloadLength(pver uint32) uint32 {
|
||||
var length uint32
|
||||
|
||||
// ChannelID - 32bytes
|
||||
length += 32
|
||||
|
||||
// Len - 2 bytes
|
||||
length += 2
|
||||
|
||||
// ScriptPubKey - 34 bytes for pay to witness script hash
|
||||
length += 34
|
||||
|
||||
// NOTE: pay to pubkey hash is 25 bytes, pay to script hash is 22
|
||||
// bytes, and pay to witness pubkey hash is 22 bytes in length.
|
||||
|
||||
return length
|
||||
}
|
||||
128
vendor/github.com/lightningnetwork/lnd/lnwire/signature.go
generated
vendored
Normal file
128
vendor/github.com/lightningnetwork/lnd/lnwire/signature.go
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
)
|
||||
|
||||
// Sig is a fixed-sized ECDSA signature. Unlike Bitcoin, we use fixed sized
|
||||
// signatures on the wire, instead of DER encoded signatures. This type
|
||||
// provides several methods to convert to/from a regular Bitcoin DER encoded
|
||||
// signature (raw bytes and *btcec.Signature).
|
||||
type Sig [64]byte
|
||||
|
||||
// NewSigFromRawSignature returns a Sig from a Bitcoin raw signature encoded in
|
||||
// the canonical DER encoding.
|
||||
func NewSigFromRawSignature(sig []byte) (Sig, error) {
|
||||
var b Sig
|
||||
|
||||
if len(sig) == 0 {
|
||||
return b, fmt.Errorf("cannot decode empty signature")
|
||||
}
|
||||
|
||||
// Extract lengths of R and S. The DER representation is laid out as
|
||||
// 0x30 <length> 0x02 <length r> r 0x02 <length s> s
|
||||
// which means the length of R is the 4th byte and the length of S
|
||||
// is the second byte after R ends. 0x02 signifies a length-prefixed,
|
||||
// zero-padded, big-endian bigint. 0x30 signifies a DER signature.
|
||||
// See the Serialize() method for btcec.Signature for details.
|
||||
rLen := sig[3]
|
||||
sLen := sig[5+rLen]
|
||||
|
||||
// Check to make sure R and S can both fit into their intended buffers.
|
||||
// We check S first because these code blocks decrement sLen and rLen
|
||||
// in the case of a 33-byte 0-padded integer returned from Serialize()
|
||||
// and rLen is used in calculating array indices for S. We can track
|
||||
// this with additional variables, but it's more efficient to just
|
||||
// check S first.
|
||||
if sLen > 32 {
|
||||
if (sLen > 33) || (sig[6+rLen] != 0x00) {
|
||||
return b, fmt.Errorf("S is over 32 bytes long " +
|
||||
"without padding")
|
||||
}
|
||||
sLen--
|
||||
copy(b[64-sLen:], sig[7+rLen:])
|
||||
} else {
|
||||
copy(b[64-sLen:], sig[6+rLen:])
|
||||
}
|
||||
|
||||
// Do the same for R as we did for S
|
||||
if rLen > 32 {
|
||||
if (rLen > 33) || (sig[4] != 0x00) {
|
||||
return b, fmt.Errorf("R is over 32 bytes long " +
|
||||
"without padding")
|
||||
}
|
||||
rLen--
|
||||
copy(b[32-rLen:], sig[5:5+rLen])
|
||||
} else {
|
||||
copy(b[32-rLen:], sig[4:4+rLen])
|
||||
}
|
||||
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// NewSigFromSignature creates a new signature as used on the wire, from an
|
||||
// existing btcec.Signature.
|
||||
func NewSigFromSignature(e *btcec.Signature) (Sig, error) {
|
||||
if e == nil {
|
||||
return Sig{}, fmt.Errorf("cannot decode empty signature")
|
||||
}
|
||||
|
||||
// Serialize the signature with all the checks that entails.
|
||||
return NewSigFromRawSignature(e.Serialize())
|
||||
}
|
||||
|
||||
// ToSignature converts the fixed-sized signature to a btcec.Signature objects
|
||||
// which can be used for signature validation checks.
|
||||
func (b *Sig) ToSignature() (*btcec.Signature, error) {
|
||||
// Parse the signature with strict checks.
|
||||
sigBytes := b.ToSignatureBytes()
|
||||
sig, err := btcec.ParseDERSignature(sigBytes, btcec.S256())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return sig, nil
|
||||
}
|
||||
|
||||
// ToSignatureBytes serializes the target fixed-sized signature into the raw
|
||||
// bytes of a DER encoding.
|
||||
func (b *Sig) ToSignatureBytes() []byte {
|
||||
// Extract canonically-padded bigint representations from buffer
|
||||
r := extractCanonicalPadding(b[0:32])
|
||||
s := extractCanonicalPadding(b[32:64])
|
||||
rLen := uint8(len(r))
|
||||
sLen := uint8(len(s))
|
||||
|
||||
// Create a canonical serialized signature. DER format is:
|
||||
// 0x30 <length> 0x02 <length r> r 0x02 <length s> s
|
||||
sigBytes := make([]byte, 6+rLen+sLen)
|
||||
sigBytes[0] = 0x30 // DER signature magic value
|
||||
sigBytes[1] = 4 + rLen + sLen // Length of rest of signature
|
||||
sigBytes[2] = 0x02 // Big integer magic value
|
||||
sigBytes[3] = rLen // Length of R
|
||||
sigBytes[rLen+4] = 0x02 // Big integer magic value
|
||||
sigBytes[rLen+5] = sLen // Length of S
|
||||
copy(sigBytes[4:], r) // Copy R
|
||||
copy(sigBytes[rLen+6:], s) // Copy S
|
||||
|
||||
return sigBytes
|
||||
}
|
||||
|
||||
// extractCanonicalPadding is a utility function to extract the canonical
|
||||
// padding of a big-endian integer from the wire encoding (a 0-padded
|
||||
// big-endian integer) such that it passes btcec.canonicalPadding test.
|
||||
func extractCanonicalPadding(b []byte) []byte {
|
||||
for i := 0; i < len(b); i++ {
|
||||
// Found first non-zero byte.
|
||||
if b[i] > 0 {
|
||||
// If the MSB is set, we need zero padding.
|
||||
if b[i]&0x80 == 0x80 {
|
||||
return append([]byte{0x00}, b[i:]...)
|
||||
}
|
||||
return b[i:]
|
||||
}
|
||||
}
|
||||
return []byte{0x00}
|
||||
}
|
||||
109
vendor/github.com/lightningnetwork/lnd/lnwire/update_add_htlc.go
generated
vendored
Normal file
109
vendor/github.com/lightningnetwork/lnd/lnwire/update_add_htlc.go
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
package lnwire
|
||||
|
||||
import "io"
|
||||
|
||||
// OnionPacketSize is the size of the serialized Sphinx onion packet included
|
||||
// in each UpdateAddHTLC message. The breakdown of the onion packet is as
|
||||
// follows: 1-byte version, 33-byte ephemeral public key (for ECDH), 1300-bytes
|
||||
// of per-hop data, and a 32-byte HMAC over the entire packet.
|
||||
const OnionPacketSize = 1366
|
||||
|
||||
// UpdateAddHTLC is the message sent by Alice to Bob when she wishes to add an
|
||||
// HTLC to his remote commitment transaction. In addition to information
|
||||
// detailing the value, the ID, expiry, and the onion blob is also included
|
||||
// which allows Bob to derive the next hop in the route. The HTLC added by this
|
||||
// message is to be added to the remote node's "pending" HTLC's. A subsequent
|
||||
// CommitSig message will move the pending HTLC to the newly created commitment
|
||||
// transaction, marking them as "staged".
|
||||
type UpdateAddHTLC struct {
|
||||
// ChanID is the particular active channel that this UpdateAddHTLC is
|
||||
// bound to.
|
||||
ChanID ChannelID
|
||||
|
||||
// ID is the identification server for this HTLC. This value is
|
||||
// explicitly included as it allows nodes to survive single-sided
|
||||
// restarts. The ID value for this sides starts at zero, and increases
|
||||
// with each offered HTLC.
|
||||
ID uint64
|
||||
|
||||
// Amount is the amount of millisatoshis this HTLC is worth.
|
||||
Amount MilliSatoshi
|
||||
|
||||
// PaymentHash is the payment hash to be included in the HTLC this
|
||||
// request creates. The pre-image to this HTLC must be revealed by the
|
||||
// upstream peer in order to fully settle the HTLC.
|
||||
PaymentHash [32]byte
|
||||
|
||||
// Expiry is the number of blocks after which this HTLC should expire.
|
||||
// It is the receiver's duty to ensure that the outgoing HTLC has a
|
||||
// sufficient expiry value to allow her to redeem the incoming HTLC.
|
||||
Expiry uint32
|
||||
|
||||
// OnionBlob is the raw serialized mix header used to route an HTLC in
|
||||
// a privacy-preserving manner. The mix header is defined currently to
|
||||
// be parsed as a 4-tuple: (groupElement, routingInfo, headerMAC,
|
||||
// body). First the receiving node should use the groupElement, and
|
||||
// its current onion key to derive a shared secret with the source.
|
||||
// Once the shared secret has been derived, the headerMAC should be
|
||||
// checked FIRST. Note that the MAC only covers the routingInfo field.
|
||||
// If the MAC matches, and the shared secret is fresh, then the node
|
||||
// should strip off a layer of encryption, exposing the next hop to be
|
||||
// used in the subsequent UpdateAddHTLC message.
|
||||
OnionBlob [OnionPacketSize]byte
|
||||
}
|
||||
|
||||
// NewUpdateAddHTLC returns a new empty UpdateAddHTLC message.
|
||||
func NewUpdateAddHTLC() *UpdateAddHTLC {
|
||||
return &UpdateAddHTLC{}
|
||||
}
|
||||
|
||||
// A compile time check to ensure UpdateAddHTLC implements the lnwire.Message
|
||||
// interface.
|
||||
var _ Message = (*UpdateAddHTLC)(nil)
|
||||
|
||||
// Decode deserializes a serialized UpdateAddHTLC message stored in the passed
|
||||
// io.Reader observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateAddHTLC) Decode(r io.Reader, pver uint32) error {
|
||||
return ReadElements(r,
|
||||
&c.ChanID,
|
||||
&c.ID,
|
||||
&c.Amount,
|
||||
c.PaymentHash[:],
|
||||
&c.Expiry,
|
||||
c.OnionBlob[:],
|
||||
)
|
||||
}
|
||||
|
||||
// Encode serializes the target UpdateAddHTLC into the passed io.Writer observing
|
||||
// the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateAddHTLC) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
c.ChanID,
|
||||
c.ID,
|
||||
c.Amount,
|
||||
c.PaymentHash[:],
|
||||
c.Expiry,
|
||||
c.OnionBlob[:],
|
||||
)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
// wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateAddHTLC) MsgType() MessageType {
|
||||
return MsgUpdateAddHTLC
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload size for an UpdateAddHTLC
|
||||
// complete message observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateAddHTLC) MaxPayloadLength(uint32) uint32 {
|
||||
// 1450
|
||||
return 32 + 8 + 4 + 8 + 32 + 1366
|
||||
}
|
||||
85
vendor/github.com/lightningnetwork/lnd/lnwire/update_fail_htlc.go
generated
vendored
Normal file
85
vendor/github.com/lightningnetwork/lnd/lnwire/update_fail_htlc.go
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
package lnwire
|
||||
|
||||
import "io"
|
||||
|
||||
// OpaqueReason is an opaque encrypted byte slice that encodes the exact
|
||||
// failure reason and additional some supplemental data. The contents of this
|
||||
// slice can only be decrypted by the sender of the original HTLC.
|
||||
type OpaqueReason []byte
|
||||
|
||||
// UpdateFailHTLC is sent by Alice to Bob in order to remove a previously added
|
||||
// HTLC. Upon receipt of an UpdateFailHTLC the HTLC should be removed from the
|
||||
// next commitment transaction, with the UpdateFailHTLC propagated backwards in
|
||||
// the route to fully undo the HTLC.
|
||||
type UpdateFailHTLC struct {
|
||||
// ChanIDPoint is the particular active channel that this
|
||||
// UpdateFailHTLC is bound to.
|
||||
ChanID ChannelID
|
||||
|
||||
// ID references which HTLC on the remote node's commitment transaction
|
||||
// has timed out.
|
||||
ID uint64
|
||||
|
||||
// Reason is an onion-encrypted blob that details why the HTLC was
|
||||
// failed. This blob is only fully decryptable by the initiator of the
|
||||
// HTLC message.
|
||||
Reason OpaqueReason
|
||||
}
|
||||
|
||||
// A compile time check to ensure UpdateFailHTLC implements the lnwire.Message
|
||||
// interface.
|
||||
var _ Message = (*UpdateFailHTLC)(nil)
|
||||
|
||||
// Decode deserializes a serialized UpdateFailHTLC message stored in the passed
|
||||
// io.Reader observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateFailHTLC) Decode(r io.Reader, pver uint32) error {
|
||||
return ReadElements(r,
|
||||
&c.ChanID,
|
||||
&c.ID,
|
||||
&c.Reason,
|
||||
)
|
||||
}
|
||||
|
||||
// Encode serializes the target UpdateFailHTLC into the passed io.Writer observing
|
||||
// the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateFailHTLC) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
c.ChanID,
|
||||
c.ID,
|
||||
c.Reason,
|
||||
)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
// wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateFailHTLC) MsgType() MessageType {
|
||||
return MsgUpdateFailHTLC
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload size for an UpdateFailHTLC
|
||||
// complete message observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateFailHTLC) MaxPayloadLength(uint32) uint32 {
|
||||
var length uint32
|
||||
|
||||
// Length of the ChanID
|
||||
length += 32
|
||||
|
||||
// Length of the ID
|
||||
length += 8
|
||||
|
||||
// Length of the length opaque reason
|
||||
length += 2
|
||||
|
||||
// Length of the Reason
|
||||
length += 292
|
||||
|
||||
return length
|
||||
}
|
||||
75
vendor/github.com/lightningnetwork/lnd/lnwire/update_fail_malformed_htlc.go
generated
vendored
Normal file
75
vendor/github.com/lightningnetwork/lnd/lnwire/update_fail_malformed_htlc.go
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"io"
|
||||
)
|
||||
|
||||
// UpdateFailMalformedHTLC is sent by either the payment forwarder or by
|
||||
// payment receiver to the payment sender in order to notify it that the onion
|
||||
// blob can't be parsed. For that reason we send this message instead of
|
||||
// obfuscate the onion failure.
|
||||
type UpdateFailMalformedHTLC struct {
|
||||
// ChanID is the particular active channel that this
|
||||
// UpdateFailMalformedHTLC is bound to.
|
||||
ChanID ChannelID
|
||||
|
||||
// ID references which HTLC on the remote node's commitment transaction
|
||||
// has timed out.
|
||||
ID uint64
|
||||
|
||||
// ShaOnionBlob hash of the onion blob on which can't be parsed by the
|
||||
// node in the payment path.
|
||||
ShaOnionBlob [sha256.Size]byte
|
||||
|
||||
// FailureCode the exact reason why onion blob haven't been parsed.
|
||||
FailureCode FailCode
|
||||
}
|
||||
|
||||
// A compile time check to ensure UpdateFailMalformedHTLC implements the
|
||||
// lnwire.Message interface.
|
||||
var _ Message = (*UpdateFailMalformedHTLC)(nil)
|
||||
|
||||
// Decode deserializes a serialized UpdateFailMalformedHTLC message stored in the passed
|
||||
// io.Reader observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateFailMalformedHTLC) Decode(r io.Reader, pver uint32) error {
|
||||
return ReadElements(r,
|
||||
&c.ChanID,
|
||||
&c.ID,
|
||||
c.ShaOnionBlob[:],
|
||||
&c.FailureCode,
|
||||
)
|
||||
}
|
||||
|
||||
// Encode serializes the target UpdateFailMalformedHTLC into the passed
|
||||
// io.Writer observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateFailMalformedHTLC) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
c.ChanID,
|
||||
c.ID,
|
||||
c.ShaOnionBlob[:],
|
||||
c.FailureCode,
|
||||
)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
// wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateFailMalformedHTLC) MsgType() MessageType {
|
||||
return MsgUpdateFailMalformedHTLC
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload size for a
|
||||
// UpdateFailMalformedHTLC complete message observing the specified protocol
|
||||
// version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateFailMalformedHTLC) MaxPayloadLength(uint32) uint32 {
|
||||
// 32 + 8 + 32 + 2
|
||||
return 74
|
||||
}
|
||||
70
vendor/github.com/lightningnetwork/lnd/lnwire/update_fee.go
generated
vendored
Normal file
70
vendor/github.com/lightningnetwork/lnd/lnwire/update_fee.go
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// UpdateFee is the message the channel initiator sends to the other peer if
|
||||
// the channel commitment fee needs to be updated.
|
||||
type UpdateFee struct {
|
||||
// ChanID is the channel that this UpdateFee is meant for.
|
||||
ChanID ChannelID
|
||||
|
||||
// FeePerKw is the fee-per-kw on commit transactions that the sender of
|
||||
// this message wants to use for this channel.
|
||||
//
|
||||
// TODO(halseth): make SatPerKWeight when fee estimation is moved to
|
||||
// own package. Currently this will cause an import cycle.
|
||||
FeePerKw uint32
|
||||
}
|
||||
|
||||
// NewUpdateFee creates a new UpdateFee message.
|
||||
func NewUpdateFee(chanID ChannelID, feePerKw uint32) *UpdateFee {
|
||||
return &UpdateFee{
|
||||
ChanID: chanID,
|
||||
FeePerKw: feePerKw,
|
||||
}
|
||||
}
|
||||
|
||||
// A compile time check to ensure UpdateFee implements the lnwire.Message
|
||||
// interface.
|
||||
var _ Message = (*UpdateFee)(nil)
|
||||
|
||||
// Decode deserializes a serialized UpdateFee message stored in the passed
|
||||
// io.Reader observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateFee) Decode(r io.Reader, pver uint32) error {
|
||||
return ReadElements(r,
|
||||
&c.ChanID,
|
||||
&c.FeePerKw,
|
||||
)
|
||||
}
|
||||
|
||||
// Encode serializes the target UpdateFee into the passed io.Writer
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateFee) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
c.ChanID,
|
||||
c.FeePerKw,
|
||||
)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
// wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateFee) MsgType() MessageType {
|
||||
return MsgUpdateFee
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload size for an UpdateFee
|
||||
// complete message observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateFee) MaxPayloadLength(uint32) uint32 {
|
||||
// 32 + 4
|
||||
return 36
|
||||
}
|
||||
78
vendor/github.com/lightningnetwork/lnd/lnwire/update_fulfill_htlc.go
generated
vendored
Normal file
78
vendor/github.com/lightningnetwork/lnd/lnwire/update_fulfill_htlc.go
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
package lnwire
|
||||
|
||||
import "io"
|
||||
|
||||
// UpdateFulfillHTLC is sent by Alice to Bob when she wishes to settle a
|
||||
// particular HTLC referenced by its HTLCKey within a specific active channel
|
||||
// referenced by ChannelPoint. A subsequent CommitSig message will be sent by
|
||||
// Alice to "lock-in" the removal of the specified HTLC, possible containing a
|
||||
// batch signature covering several settled HTLC's.
|
||||
type UpdateFulfillHTLC struct {
|
||||
// ChanID references an active channel which holds the HTLC to be
|
||||
// settled.
|
||||
ChanID ChannelID
|
||||
|
||||
// ID denotes the exact HTLC stage within the receiving node's
|
||||
// commitment transaction to be removed.
|
||||
ID uint64
|
||||
|
||||
// PaymentPreimage is the R-value preimage required to fully settle an
|
||||
// HTLC.
|
||||
PaymentPreimage [32]byte
|
||||
}
|
||||
|
||||
// NewUpdateFulfillHTLC returns a new empty UpdateFulfillHTLC.
|
||||
func NewUpdateFulfillHTLC(chanID ChannelID, id uint64,
|
||||
preimage [32]byte) *UpdateFulfillHTLC {
|
||||
|
||||
return &UpdateFulfillHTLC{
|
||||
ChanID: chanID,
|
||||
ID: id,
|
||||
PaymentPreimage: preimage,
|
||||
}
|
||||
}
|
||||
|
||||
// A compile time check to ensure UpdateFulfillHTLC implements the lnwire.Message
|
||||
// interface.
|
||||
var _ Message = (*UpdateFulfillHTLC)(nil)
|
||||
|
||||
// Decode deserializes a serialized UpdateFulfillHTLC message stored in the passed
|
||||
// io.Reader observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateFulfillHTLC) Decode(r io.Reader, pver uint32) error {
|
||||
return ReadElements(r,
|
||||
&c.ChanID,
|
||||
&c.ID,
|
||||
c.PaymentPreimage[:],
|
||||
)
|
||||
}
|
||||
|
||||
// Encode serializes the target UpdateFulfillHTLC into the passed io.Writer
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateFulfillHTLC) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
c.ChanID,
|
||||
c.ID,
|
||||
c.PaymentPreimage[:],
|
||||
)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
// wire.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateFulfillHTLC) MsgType() MessageType {
|
||||
return MsgUpdateFulfillHTLC
|
||||
}
|
||||
|
||||
// MaxPayloadLength returns the maximum allowed payload size for an UpdateFulfillHTLC
|
||||
// complete message observing the specified protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateFulfillHTLC) MaxPayloadLength(uint32) uint32 {
|
||||
// 32 + 8 + 32
|
||||
return 72
|
||||
}
|
||||
19
vendor/github.com/lightningnetwork/lnd/queue/LICENSE
generated
vendored
Normal file
19
vendor/github.com/lightningnetwork/lnd/queue/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (C) 2015-2018 Lightning Labs and The Lightning Network Developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
196
vendor/github.com/lightningnetwork/lnd/queue/gc_queue.go
generated
vendored
Normal file
196
vendor/github.com/lightningnetwork/lnd/queue/gc_queue.go
generated
vendored
Normal file
@@ -0,0 +1,196 @@
|
||||
package queue
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/lightningnetwork/lnd/ticker"
|
||||
)
|
||||
|
||||
// GCQueue is garbage collecting queue, which dynamically grows and contracts
|
||||
// based on load. If the queue has items which have been returned, the queue
|
||||
// will check every gcInterval amount of time to see if any elements are
|
||||
// eligible to be released back to the runtime. Elements that have been in the
|
||||
// queue for a duration of least expiryInterval will be released upon the next
|
||||
// iteration of the garbage collection, thus the maximum amount of time an
|
||||
// element remain in the queue is expiryInterval+gcInterval. The gc ticker will
|
||||
// be disabled after all items in the queue have been taken or released to
|
||||
// ensure that the GCQueue becomes quiescent, and imposes minimal overhead in
|
||||
// the steady state.
|
||||
type GCQueue struct {
|
||||
// takeBuffer coordinates the delivery of items taken from the queue
|
||||
// such that they are delivered to requesters.
|
||||
takeBuffer chan interface{}
|
||||
|
||||
// returnBuffer coordinates the return of items back into the queue,
|
||||
// where they will be kept until retaken or released.
|
||||
returnBuffer chan interface{}
|
||||
|
||||
// newItem is a constructor, used to generate new elements if none are
|
||||
// otherwise available for reuse.
|
||||
newItem func() interface{}
|
||||
|
||||
// expiryInterval is the minimum amount of time an element will remain
|
||||
// in the queue before being released.
|
||||
expiryInterval time.Duration
|
||||
|
||||
// recycleTicker is a resumable ticker used to trigger a sweep to
|
||||
// release elements that have been in the queue longer than
|
||||
// expiryInterval.
|
||||
recycleTicker ticker.Ticker
|
||||
|
||||
// freeList maintains a list of gcQueueEntries, sorted in order of
|
||||
// increasing time of arrival.
|
||||
freeList *list.List
|
||||
|
||||
wg sync.WaitGroup
|
||||
quit chan struct{}
|
||||
}
|
||||
|
||||
// NewGCQueue creates a new garbage collecting queue, which dynamically grows
|
||||
// and contracts based on load. If the queue has items which have been returned,
|
||||
// the queue will check every gcInterval amount of time to see if any elements
|
||||
// are eligible to be released back to the runtime. Elements that have been in
|
||||
// the queue for a duration of least expiryInterval will be released upon the
|
||||
// next iteration of the garbage collection, thus the maximum amount of time an
|
||||
// element remain in the queue is expiryInterval+gcInterval. The gc ticker will
|
||||
// be disabled after all items in the queue have been taken or released to
|
||||
// ensure that the GCQueue becomes quiescent, and imposes minimal overhead in
|
||||
// the steady state. The returnQueueSize parameter is used to size the maximal
|
||||
// number of items that can be returned without being dropped during large
|
||||
// bursts in attempts to return items to the GCQUeue.
|
||||
func NewGCQueue(newItem func() interface{}, returnQueueSize int,
|
||||
gcInterval, expiryInterval time.Duration) *GCQueue {
|
||||
|
||||
q := &GCQueue{
|
||||
takeBuffer: make(chan interface{}),
|
||||
returnBuffer: make(chan interface{}, returnQueueSize),
|
||||
expiryInterval: expiryInterval,
|
||||
freeList: list.New(),
|
||||
recycleTicker: ticker.New(gcInterval),
|
||||
newItem: newItem,
|
||||
quit: make(chan struct{}),
|
||||
}
|
||||
|
||||
go q.queueManager()
|
||||
|
||||
return q
|
||||
}
|
||||
|
||||
// Take returns either a recycled element from the queue, or creates a new item
|
||||
// if none are available.
|
||||
func (q *GCQueue) Take() interface{} {
|
||||
select {
|
||||
case item := <-q.takeBuffer:
|
||||
return item
|
||||
case <-time.After(time.Millisecond):
|
||||
return q.newItem()
|
||||
}
|
||||
}
|
||||
|
||||
// Return adds the returned item to freelist if the queue's returnBuffer has
|
||||
// available capacity. Under load, items may be dropped to ensure this method
|
||||
// does not block.
|
||||
func (q *GCQueue) Return(item interface{}) {
|
||||
select {
|
||||
case q.returnBuffer <- item:
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
// gcQueueEntry is a tuple containing an interface{} and the time at which the
|
||||
// item was added to the queue. The recorded time is used to determine when the
|
||||
// entry becomes stale, and can be released if it has not already been taken.
|
||||
type gcQueueEntry struct {
|
||||
item interface{}
|
||||
time time.Time
|
||||
}
|
||||
|
||||
// queueManager maintains the free list of elements by popping the head of the
|
||||
// queue when items are needed, and appending them to the end of the queue when
|
||||
// items are returned. The queueManager will periodically attempt to release any
|
||||
// items that have been in the queue longer than the expiry interval.
|
||||
//
|
||||
// NOTE: This method SHOULD be run as a goroutine.
|
||||
func (q *GCQueue) queueManager() {
|
||||
for {
|
||||
// If the pool is empty, initialize a buffer pool to serve a
|
||||
// client that takes a buffer immediately. If this happens, this
|
||||
// is either:
|
||||
// 1) the first iteration of the loop,
|
||||
// 2) after all entries were garbage collected, or
|
||||
// 3) the freelist was emptied after the last entry was taken.
|
||||
//
|
||||
// In all of these cases, it is safe to pause the recycle ticker
|
||||
// since it will be resumed as soon an entry is returned to the
|
||||
// freelist.
|
||||
if q.freeList.Len() == 0 {
|
||||
q.freeList.PushBack(gcQueueEntry{
|
||||
item: q.newItem(),
|
||||
time: time.Now(),
|
||||
})
|
||||
|
||||
q.recycleTicker.Pause()
|
||||
}
|
||||
|
||||
next := q.freeList.Front()
|
||||
|
||||
select {
|
||||
|
||||
// If a client requests a new write buffer, deliver the buffer
|
||||
// at the head of the freelist to them.
|
||||
case q.takeBuffer <- next.Value.(gcQueueEntry).item:
|
||||
q.freeList.Remove(next)
|
||||
|
||||
// If a client is returning a write buffer, add it to the free
|
||||
// list and resume the recycle ticker so that it can be cleared
|
||||
// if the entries are not quickly reused.
|
||||
case item := <-q.returnBuffer:
|
||||
// Add the returned buffer to the freelist, recording
|
||||
// the current time so we can determine when the entry
|
||||
// expires.
|
||||
q.freeList.PushBack(gcQueueEntry{
|
||||
item: item,
|
||||
time: time.Now(),
|
||||
})
|
||||
|
||||
// Adding the buffer implies that we now have a non-zero
|
||||
// number of elements in the free list. Resume the
|
||||
// recycle ticker to cleanup any entries that go unused.
|
||||
q.recycleTicker.Resume()
|
||||
|
||||
// If the recycle ticker fires, we will aggresively release any
|
||||
// write buffers in the freelist for which the expiryInterval
|
||||
// has elapsed since their insertion. If after doing so, no
|
||||
// elements remain, we will pause the recylce ticker.
|
||||
case <-q.recycleTicker.Ticks():
|
||||
// Since the insert time of all entries will be
|
||||
// monotonically increasing, iterate over elements and
|
||||
// remove all entries that have expired.
|
||||
var next *list.Element
|
||||
for e := q.freeList.Front(); e != nil; e = next {
|
||||
// Cache the next element, since it will become
|
||||
// unreachable from the current element if it is
|
||||
// removed.
|
||||
next = e.Next()
|
||||
entry := e.Value.(gcQueueEntry)
|
||||
|
||||
// Use now - insertTime <= expiryInterval to
|
||||
// determine if this entry has not expired.
|
||||
if time.Since(entry.time) <= q.expiryInterval {
|
||||
// If this entry hasn't expired, then
|
||||
// all entries that follow will still be
|
||||
// valid.
|
||||
break
|
||||
}
|
||||
|
||||
// Otherwise, remove the expired entry from the
|
||||
// linked-list.
|
||||
q.freeList.Remove(e)
|
||||
entry.item = nil
|
||||
e.Value = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
5
vendor/github.com/lightningnetwork/lnd/queue/go.mod
generated
vendored
Normal file
5
vendor/github.com/lightningnetwork/lnd/queue/go.mod
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
module github.com/lightningnetwork/lnd/queue
|
||||
|
||||
require github.com/lightningnetwork/lnd/ticker v1.0.0
|
||||
|
||||
replace github.com/lightningnetwork/lnd/ticker v1.0.0 => ../ticker
|
||||
2
vendor/github.com/lightningnetwork/lnd/queue/go.sum
generated
vendored
Normal file
2
vendor/github.com/lightningnetwork/lnd/queue/go.sum
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
github.com/lightningnetwork/lnd/ticker v1.0.0 h1:S1b60TEGoTtCe2A0yeB+ecoj/kkS4qpwh6l+AkQEZwU=
|
||||
github.com/lightningnetwork/lnd/ticker v1.0.0/go.mod h1:iaLXJiVgI1sPANIF2qYYUJXjoksPNvGNYowB8aRbpX0=
|
||||
105
vendor/github.com/lightningnetwork/lnd/queue/queue.go
generated
vendored
Normal file
105
vendor/github.com/lightningnetwork/lnd/queue/queue.go
generated
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
package queue
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// ConcurrentQueue is a concurrent-safe FIFO queue with unbounded capacity.
|
||||
// Clients interact with the queue by pushing items into the in channel and
|
||||
// popping items from the out channel. There is a goroutine that manages moving
|
||||
// items from the in channel to the out channel in the correct order that must
|
||||
// be started by calling Start().
|
||||
type ConcurrentQueue struct {
|
||||
started uint32 // to be used atomically
|
||||
stopped uint32 // to be used atomically
|
||||
|
||||
chanIn chan interface{}
|
||||
chanOut chan interface{}
|
||||
overflow *list.List
|
||||
|
||||
wg sync.WaitGroup
|
||||
quit chan struct{}
|
||||
}
|
||||
|
||||
// NewConcurrentQueue constructs a ConcurrentQueue. The bufferSize parameter is
|
||||
// the capacity of the output channel. When the size of the queue is below this
|
||||
// threshold, pushes do not incur the overhead of the less efficient overflow
|
||||
// structure.
|
||||
func NewConcurrentQueue(bufferSize int) *ConcurrentQueue {
|
||||
return &ConcurrentQueue{
|
||||
chanIn: make(chan interface{}),
|
||||
chanOut: make(chan interface{}, bufferSize),
|
||||
overflow: list.New(),
|
||||
quit: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
// ChanIn returns a channel that can be used to push new items into the queue.
|
||||
func (cq *ConcurrentQueue) ChanIn() chan<- interface{} {
|
||||
return cq.chanIn
|
||||
}
|
||||
|
||||
// ChanOut returns a channel that can be used to pop items from the queue.
|
||||
func (cq *ConcurrentQueue) ChanOut() <-chan interface{} {
|
||||
return cq.chanOut
|
||||
}
|
||||
|
||||
// Start begins a goroutine that manages moving items from the in channel to the
|
||||
// out channel. The queue tries to move items directly to the out channel
|
||||
// minimize overhead, but if the out channel is full it pushes items to an
|
||||
// overflow queue. This must be called before using the queue.
|
||||
func (cq *ConcurrentQueue) Start() {
|
||||
if !atomic.CompareAndSwapUint32(&cq.started, 0, 1) {
|
||||
return
|
||||
}
|
||||
|
||||
cq.wg.Add(1)
|
||||
go func() {
|
||||
defer cq.wg.Done()
|
||||
|
||||
for {
|
||||
nextElement := cq.overflow.Front()
|
||||
if nextElement == nil {
|
||||
// Overflow queue is empty so incoming items can be pushed
|
||||
// directly to the output channel. If output channel is full
|
||||
// though, push to overflow.
|
||||
select {
|
||||
case item := <-cq.chanIn:
|
||||
select {
|
||||
case cq.chanOut <- item:
|
||||
// Optimistically push directly to chanOut
|
||||
default:
|
||||
cq.overflow.PushBack(item)
|
||||
}
|
||||
case <-cq.quit:
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// Overflow queue is not empty, so any new items get pushed to
|
||||
// the back to preserve order.
|
||||
select {
|
||||
case item := <-cq.chanIn:
|
||||
cq.overflow.PushBack(item)
|
||||
case cq.chanOut <- nextElement.Value:
|
||||
cq.overflow.Remove(nextElement)
|
||||
case <-cq.quit:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Stop ends the goroutine that moves items from the in channel to the out
|
||||
// channel. This does not clear the queue state, so the queue can be restarted
|
||||
// without dropping items.
|
||||
func (cq *ConcurrentQueue) Stop() {
|
||||
if !atomic.CompareAndSwapUint32(&cq.stopped, 0, 1) {
|
||||
return
|
||||
}
|
||||
|
||||
close(cq.quit)
|
||||
cq.wg.Wait()
|
||||
}
|
||||
19
vendor/github.com/lightningnetwork/lnd/ticker/LICENSE
generated
vendored
Normal file
19
vendor/github.com/lightningnetwork/lnd/ticker/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright (C) 2015-2018 Lightning Labs and The Lightning Network Developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
105
vendor/github.com/lightningnetwork/lnd/ticker/force.go
generated
vendored
Normal file
105
vendor/github.com/lightningnetwork/lnd/ticker/force.go
generated
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
package ticker
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Force implements the Ticker interface, and provides a method of force-feeding
|
||||
// ticks, even while paused.
|
||||
type Force struct {
|
||||
isActive uint32 // used atomically
|
||||
|
||||
// Force is used to force-feed a ticks into the ticker. Useful for
|
||||
// debugging when trying to wake an event.
|
||||
Force chan time.Time
|
||||
|
||||
ticker <-chan time.Time
|
||||
skip chan struct{}
|
||||
|
||||
wg sync.WaitGroup
|
||||
quit chan struct{}
|
||||
}
|
||||
|
||||
// A compile-time constraint to ensure Force satisfies the Ticker interface.
|
||||
var _ Ticker = (*Force)(nil)
|
||||
|
||||
// NewForce returns a Force ticker, used for testing and debugging. It supports
|
||||
// the ability to force-feed events that get output by the
|
||||
func NewForce(interval time.Duration) *Force {
|
||||
m := &Force{
|
||||
ticker: time.NewTicker(interval).C,
|
||||
Force: make(chan time.Time),
|
||||
skip: make(chan struct{}),
|
||||
quit: make(chan struct{}),
|
||||
}
|
||||
|
||||
// Proxy the real ticks to our Force channel if we are active.
|
||||
m.wg.Add(1)
|
||||
go func() {
|
||||
defer m.wg.Done()
|
||||
for {
|
||||
select {
|
||||
case t := <-m.ticker:
|
||||
if atomic.LoadUint32(&m.isActive) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
select {
|
||||
case m.Force <- t:
|
||||
case <-m.skip:
|
||||
case <-m.quit:
|
||||
return
|
||||
}
|
||||
|
||||
case <-m.quit:
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// Ticks returns a receive-only channel that delivers times at the ticker's
|
||||
// prescribed interval when active. Force-fed ticks can be delivered at any
|
||||
// time.
|
||||
//
|
||||
// NOTE: Part of the Ticker interface.
|
||||
func (m *Force) Ticks() <-chan time.Time {
|
||||
return m.Force
|
||||
}
|
||||
|
||||
// Resume starts underlying time.Ticker and causes the ticker to begin
|
||||
// delivering scheduled events.
|
||||
//
|
||||
// NOTE: Part of the Ticker interface.
|
||||
func (m *Force) Resume() {
|
||||
atomic.StoreUint32(&m.isActive, 1)
|
||||
}
|
||||
|
||||
// Pause suspends the underlying ticker, such that Ticks() stops signaling at
|
||||
// regular intervals.
|
||||
//
|
||||
// NOTE: Part of the Ticker interface.
|
||||
func (m *Force) Pause() {
|
||||
atomic.StoreUint32(&m.isActive, 0)
|
||||
|
||||
// If the ticker fired and read isActive as true, it may still send the
|
||||
// tick. We'll try to send on the skip channel to drop it.
|
||||
select {
|
||||
case m.skip <- struct{}{}:
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
// Stop suspends the underlying ticker, such that Ticks() stops signaling at
|
||||
// regular intervals, and permanently frees up any resources.
|
||||
//
|
||||
// NOTE: Part of the Ticker interface.
|
||||
func (m *Force) Stop() {
|
||||
m.Pause()
|
||||
close(m.quit)
|
||||
m.wg.Wait()
|
||||
}
|
||||
1
vendor/github.com/lightningnetwork/lnd/ticker/go.mod
generated
vendored
Normal file
1
vendor/github.com/lightningnetwork/lnd/ticker/go.mod
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
module github.com/lightningnetwork/lnd/ticker
|
||||
126
vendor/github.com/lightningnetwork/lnd/ticker/ticker.go
generated
vendored
Normal file
126
vendor/github.com/lightningnetwork/lnd/ticker/ticker.go
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
package ticker
|
||||
|
||||
import "time"
|
||||
|
||||
// Ticker defines a resumable ticker interface, whose activity can be toggled to
|
||||
// free up resources during periods of inactivity.
|
||||
//
|
||||
// Example of resuming ticker:
|
||||
//
|
||||
// ticker.Resume() // can remove to keep inactive at first
|
||||
// defer ticker.Stop()
|
||||
// for {
|
||||
// select {
|
||||
// case <-ticker.Tick():
|
||||
// if shouldGoInactive {
|
||||
// ticker.Pause()
|
||||
// continue
|
||||
// }
|
||||
// ...
|
||||
//
|
||||
// case <-otherEvent:
|
||||
// ...
|
||||
// if shouldGoActive {
|
||||
// ticker.Resume()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// NOTE: ONE DOES NOT SIMPLY assume that Tickers are safe for concurrent access.
|
||||
type Ticker interface {
|
||||
// Ticks returns a read-only channel delivering ticks according to a
|
||||
// prescribed interval. The value returned does not need to be the same
|
||||
// channel, and may be nil.
|
||||
//
|
||||
// NOTE: Callers should assume that reads from Ticks() are stale after
|
||||
// any invocations of Resume, Pause, or Stop.
|
||||
Ticks() <-chan time.Time
|
||||
|
||||
// Resume starts or resumes the underlying ticker, such that Ticks()
|
||||
// will fire at regular intervals. After calling Resume, Ticks() should
|
||||
// minimally send ticks at the prescribed interval.
|
||||
//
|
||||
// NOTE: It MUST be safe to call Resume at any time, and more than once
|
||||
// successively.
|
||||
Resume()
|
||||
|
||||
// Pause suspends the underlying ticker, such that Ticks() stops
|
||||
// signaling at regular intervals. After calling Pause, the ticker
|
||||
// should not send any ticks scheduled with the chosen interval. Forced
|
||||
// ticks are still permissible, as in the case of the Force Ticker.
|
||||
//
|
||||
// NOTE: It MUST be safe to call Pause at any time, and more than once
|
||||
// successively.
|
||||
Pause()
|
||||
|
||||
// Stop suspends the underlying ticker, such that Ticks() stops
|
||||
// signaling at regular intervals, and permanently frees up any
|
||||
// remaining resources.
|
||||
//
|
||||
// NOTE: The behavior of a Ticker is undefined after calling Stop.
|
||||
Stop()
|
||||
}
|
||||
|
||||
// T is the production implementation of the resumable Ticker interface. This
|
||||
// allows various components to toggle their need for tick events, which may
|
||||
// vary depending on system load.
|
||||
type T struct {
|
||||
// interval is the desired duration between ticks when active.
|
||||
interval time.Duration
|
||||
|
||||
// ticker is the ephemeral, underlying time.Ticker. We keep a reference
|
||||
// to this ticker so that it can be stopped and cleaned up on Pause or
|
||||
// Stop.
|
||||
ticker *time.Ticker
|
||||
}
|
||||
|
||||
// A compile-time constraint to ensure T satisfies the Ticker interface.
|
||||
var _ Ticker = (*T)(nil)
|
||||
|
||||
// New returns a new ticker that signals with the given interval when not
|
||||
// paused. The ticker starts off inactive.
|
||||
func New(interval time.Duration) *T {
|
||||
return &T{
|
||||
interval: interval,
|
||||
}
|
||||
}
|
||||
|
||||
// Ticks returns a receive-only channel that delivers times at the ticker's
|
||||
// prescribed interval. This method returns nil when the ticker is paused.
|
||||
//
|
||||
// NOTE: Part of the Ticker interface.
|
||||
func (t *T) Ticks() <-chan time.Time {
|
||||
if t.ticker == nil {
|
||||
return nil
|
||||
}
|
||||
return t.ticker.C
|
||||
}
|
||||
|
||||
// Resume starts underlying time.Ticker and causes the ticker to begin
|
||||
// delivering scheduled events.
|
||||
//
|
||||
// NOTE: Part of the Ticker interface.
|
||||
func (t *T) Resume() {
|
||||
if t.ticker == nil {
|
||||
t.ticker = time.NewTicker(t.interval)
|
||||
}
|
||||
}
|
||||
|
||||
// Pause suspends the underlying ticker, such that Ticks() stops signaling at
|
||||
// regular intervals.
|
||||
//
|
||||
// NOTE: Part of the Ticker interface.
|
||||
func (t *T) Pause() {
|
||||
if t.ticker != nil {
|
||||
t.ticker.Stop()
|
||||
t.ticker = nil
|
||||
}
|
||||
}
|
||||
|
||||
// Stop suspends the underlying ticker, such that Ticks() stops signaling at
|
||||
// regular intervals, and permanently frees up any resources. For this
|
||||
// implementation, this is equivalent to Pause.
|
||||
//
|
||||
// NOTE: Part of the Ticker interface.
|
||||
func (t *T) Stop() {
|
||||
t.Pause()
|
||||
}
|
||||
21
vendor/github.com/lightningnetwork/lnd/tor/README.md
generated
vendored
Normal file
21
vendor/github.com/lightningnetwork/lnd/tor/README.md
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
tor
|
||||
===
|
||||
|
||||
The tor package contains utility functions that allow for interacting with the
|
||||
Tor daemon. So far, supported functions include:
|
||||
|
||||
* Routing all traffic over Tor's exposed SOCKS5 proxy.
|
||||
* Routing DNS queries over Tor (A, AAAA, SRV).
|
||||
* Limited Tor Control functionality (synchronous messages only). So far, this
|
||||
includes:
|
||||
* Support for SAFECOOKIE authentication only as a sane default.
|
||||
* Creating v2 onion services.
|
||||
|
||||
In the future, the Tor Control functionality will be extended to support v3
|
||||
onion services, asynchronous messages, etc.
|
||||
|
||||
## Installation and Updating
|
||||
|
||||
```bash
|
||||
$ go get -u github.com/lightningnetwork/lnd/tor
|
||||
```
|
||||
530
vendor/github.com/lightningnetwork/lnd/tor/controller.go
generated
vendored
Normal file
530
vendor/github.com/lightningnetwork/lnd/tor/controller.go
generated
vendored
Normal file
@@ -0,0 +1,530 @@
|
||||
package tor
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/hmac"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/textproto"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
const (
|
||||
// success is the Tor Control response code representing a successful
|
||||
// request.
|
||||
success = 250
|
||||
|
||||
// nonceLen is the length of a nonce generated by either the controller
|
||||
// or the Tor server
|
||||
nonceLen = 32
|
||||
|
||||
// cookieLen is the length of the authentication cookie.
|
||||
cookieLen = 32
|
||||
|
||||
// ProtocolInfoVersion is the `protocolinfo` version currently supported
|
||||
// by the Tor server.
|
||||
ProtocolInfoVersion = 1
|
||||
|
||||
// MinTorVersion is the minimum supported version that the Tor server
|
||||
// must be running on. This is needed in order to create v3 onion
|
||||
// services through Tor's control port.
|
||||
MinTorVersion = "0.3.3.6"
|
||||
)
|
||||
|
||||
var (
|
||||
// serverKey is the key used when computing the HMAC-SHA256 of a message
|
||||
// from the server.
|
||||
serverKey = []byte("Tor safe cookie authentication " +
|
||||
"server-to-controller hash")
|
||||
|
||||
// controllerKey is the key used when computing the HMAC-SHA256 of a
|
||||
// message from the controller.
|
||||
controllerKey = []byte("Tor safe cookie authentication " +
|
||||
"controller-to-server hash")
|
||||
)
|
||||
|
||||
// Controller is an implementation of the Tor Control protocol. This is used in
|
||||
// order to communicate with a Tor server. Its only supported method of
|
||||
// authentication is the SAFECOOKIE method.
|
||||
//
|
||||
// NOTE: The connection to the Tor server must be authenticated before
|
||||
// proceeding to send commands. Otherwise, the connection will be closed.
|
||||
//
|
||||
// TODO:
|
||||
// * if adding support for more commands, extend this with a command queue?
|
||||
// * place under sub-package?
|
||||
// * support async replies from the server
|
||||
type Controller struct {
|
||||
// started is used atomically in order to prevent multiple calls to
|
||||
// Start.
|
||||
started int32
|
||||
|
||||
// stopped is used atomically in order to prevent multiple calls to
|
||||
// Stop.
|
||||
stopped int32
|
||||
|
||||
// conn is the underlying connection between the controller and the
|
||||
// Tor server. It provides read and write methods to simplify the
|
||||
// text-based messages within the connection.
|
||||
conn *textproto.Conn
|
||||
|
||||
// controlAddr is the host:port the Tor server is listening locally for
|
||||
// controller connections on.
|
||||
controlAddr string
|
||||
|
||||
// version is the current version of the Tor server.
|
||||
version string
|
||||
}
|
||||
|
||||
// NewController returns a new Tor controller that will be able to interact with
|
||||
// a Tor server.
|
||||
func NewController(controlAddr string) *Controller {
|
||||
return &Controller{controlAddr: controlAddr}
|
||||
}
|
||||
|
||||
// Start establishes and authenticates the connection between the controller and
|
||||
// a Tor server. Once done, the controller will be able to send commands and
|
||||
// expect responses.
|
||||
func (c *Controller) Start() error {
|
||||
if !atomic.CompareAndSwapInt32(&c.started, 0, 1) {
|
||||
return nil
|
||||
}
|
||||
|
||||
conn, err := textproto.Dial("tcp", c.controlAddr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to connect to Tor server: %v", err)
|
||||
}
|
||||
|
||||
c.conn = conn
|
||||
|
||||
return c.authenticate()
|
||||
}
|
||||
|
||||
// Stop closes the connection between the controller and the Tor server.
|
||||
func (c *Controller) Stop() error {
|
||||
if !atomic.CompareAndSwapInt32(&c.stopped, 0, 1) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return c.conn.Close()
|
||||
}
|
||||
|
||||
// sendCommand sends a command to the Tor server and returns its response, as a
|
||||
// single space-delimited string, and code.
|
||||
func (c *Controller) sendCommand(command string) (int, string, error) {
|
||||
if err := c.conn.Writer.PrintfLine(command); err != nil {
|
||||
return 0, "", err
|
||||
}
|
||||
|
||||
// We'll use ReadResponse as it has built-in support for multi-line
|
||||
// text protocol responses.
|
||||
code, reply, err := c.conn.Reader.ReadResponse(success)
|
||||
if err != nil {
|
||||
return code, reply, err
|
||||
}
|
||||
|
||||
return code, reply, nil
|
||||
}
|
||||
|
||||
// parseTorReply parses the reply from the Tor server after receiving a command
|
||||
// from a controller. This will parse the relevant reply parameters into a map
|
||||
// of keys and values.
|
||||
func parseTorReply(reply string) map[string]string {
|
||||
params := make(map[string]string)
|
||||
|
||||
// Replies can either span single or multiple lines, so we'll default
|
||||
// to stripping whitespace and newlines in order to retrieve the
|
||||
// individual contents of it. The -1 indicates that we want this to span
|
||||
// across all instances of a newline.
|
||||
contents := strings.Split(strings.Replace(reply, "\n", " ", -1), " ")
|
||||
for _, content := range contents {
|
||||
// Each parameter within the reply should be of the form
|
||||
// "KEY=VALUE". If the parameter doesn't contain "=", then we
|
||||
// can assume it does not provide any other relevant information
|
||||
// already known.
|
||||
keyValue := strings.SplitN(content, "=", 2)
|
||||
if len(keyValue) != 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
key := keyValue[0]
|
||||
value := keyValue[1]
|
||||
params[key] = value
|
||||
}
|
||||
|
||||
return params
|
||||
}
|
||||
|
||||
// authenticate authenticates the connection between the controller and the
|
||||
// Tor server using the SAFECOOKIE or NULL authentication method.
|
||||
func (c *Controller) authenticate() error {
|
||||
// Before proceeding to authenticate the connection, we'll retrieve
|
||||
// the authentication cookie of the Tor server. This will be used
|
||||
// throughout the authentication routine. We do this before as once the
|
||||
// authentication routine has begun, it is not possible to retrieve it
|
||||
// mid-way.
|
||||
cookie, err := c.getAuthCookie()
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to retrieve authentication cookie: "+
|
||||
"%v", err)
|
||||
}
|
||||
|
||||
// If cookie is empty and there's no error, we have a NULL
|
||||
// authentication method that we should use instead.
|
||||
if len(cookie) == 0 {
|
||||
_, _, err := c.sendCommand("AUTHENTICATE")
|
||||
return err
|
||||
}
|
||||
|
||||
// Authenticating using the SAFECOOKIE authentication method is a two
|
||||
// step process. We'll kick off the authentication routine by sending
|
||||
// the AUTHCHALLENGE command followed by a hex-encoded 32-byte nonce.
|
||||
clientNonce := make([]byte, nonceLen)
|
||||
if _, err := rand.Read(clientNonce); err != nil {
|
||||
return fmt.Errorf("unable to generate client nonce: %v", err)
|
||||
}
|
||||
|
||||
cmd := fmt.Sprintf("AUTHCHALLENGE SAFECOOKIE %x", clientNonce)
|
||||
_, reply, err := c.sendCommand(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If successful, the reply from the server should be of the following
|
||||
// format:
|
||||
//
|
||||
// "250 AUTHCHALLENGE"
|
||||
// SP "SERVERHASH=" ServerHash
|
||||
// SP "SERVERNONCE=" ServerNonce
|
||||
// CRLF
|
||||
//
|
||||
// We're interested in retrieving the SERVERHASH and SERVERNONCE
|
||||
// parameters, so we'll parse our reply to do so.
|
||||
replyParams := parseTorReply(reply)
|
||||
|
||||
// Once retrieved, we'll ensure these values are of proper length when
|
||||
// decoded.
|
||||
serverHash, ok := replyParams["SERVERHASH"]
|
||||
if !ok {
|
||||
return errors.New("server hash not found in reply")
|
||||
}
|
||||
decodedServerHash, err := hex.DecodeString(serverHash)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to decode server hash: %v", err)
|
||||
}
|
||||
if len(decodedServerHash) != sha256.Size {
|
||||
return errors.New("invalid server hash length")
|
||||
}
|
||||
|
||||
serverNonce, ok := replyParams["SERVERNONCE"]
|
||||
if !ok {
|
||||
return errors.New("server nonce not found in reply")
|
||||
}
|
||||
decodedServerNonce, err := hex.DecodeString(serverNonce)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to decode server nonce: %v", err)
|
||||
}
|
||||
if len(decodedServerNonce) != nonceLen {
|
||||
return errors.New("invalid server nonce length")
|
||||
}
|
||||
|
||||
// The server hash above was constructed by computing the HMAC-SHA256
|
||||
// of the message composed of the cookie, client nonce, and server
|
||||
// nonce. We'll redo this computation ourselves to ensure the integrity
|
||||
// and authentication of the message.
|
||||
hmacMessage := bytes.Join(
|
||||
[][]byte{cookie, clientNonce, decodedServerNonce}, []byte{},
|
||||
)
|
||||
computedServerHash := computeHMAC256(serverKey, hmacMessage)
|
||||
if !hmac.Equal(computedServerHash, decodedServerHash) {
|
||||
return fmt.Errorf("expected server hash %x, got %x",
|
||||
decodedServerHash, computedServerHash)
|
||||
}
|
||||
|
||||
// If the MAC check was successful, we'll proceed with the last step of
|
||||
// the authentication routine. We'll now send the AUTHENTICATE command
|
||||
// followed by a hex-encoded client hash constructed by computing the
|
||||
// HMAC-SHA256 of the same message, but this time using the controller's
|
||||
// key.
|
||||
clientHash := computeHMAC256(controllerKey, hmacMessage)
|
||||
if len(clientHash) != sha256.Size {
|
||||
return errors.New("invalid client hash length")
|
||||
}
|
||||
|
||||
cmd = fmt.Sprintf("AUTHENTICATE %x", clientHash)
|
||||
if _, _, err := c.sendCommand(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getAuthCookie retrieves the authentication cookie in bytes from the Tor
|
||||
// server. Cookie authentication must be enabled for this to work. The boolean
|
||||
func (c *Controller) getAuthCookie() ([]byte, error) {
|
||||
// Retrieve the authentication methods currently supported by the Tor
|
||||
// server.
|
||||
authMethods, cookieFilePath, version, err := c.ProtocolInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// With the version retrieved, we'll cache it now in case it needs to be
|
||||
// used later on.
|
||||
c.version = version
|
||||
|
||||
// Ensure that the Tor server supports the SAFECOOKIE authentication
|
||||
// method or the NULL method. If NULL, we don't need the cookie info
|
||||
// below this loop, so we just return.
|
||||
safeCookieSupport := false
|
||||
for _, authMethod := range authMethods {
|
||||
if authMethod == "SAFECOOKIE" {
|
||||
safeCookieSupport = true
|
||||
}
|
||||
if authMethod == "NULL" {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
if !safeCookieSupport {
|
||||
return nil, errors.New("the Tor server is currently not " +
|
||||
"configured for cookie or null authentication")
|
||||
}
|
||||
|
||||
// Read the cookie from the file and ensure it has the correct length.
|
||||
cookie, err := ioutil.ReadFile(cookieFilePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(cookie) != cookieLen {
|
||||
return nil, errors.New("invalid authentication cookie length")
|
||||
}
|
||||
|
||||
return cookie, nil
|
||||
}
|
||||
|
||||
// computeHMAC256 computes the HMAC-SHA256 of a key and message.
|
||||
func computeHMAC256(key, message []byte) []byte {
|
||||
mac := hmac.New(sha256.New, key)
|
||||
mac.Write(message)
|
||||
return mac.Sum(nil)
|
||||
}
|
||||
|
||||
// supportsV3 is a helper function that parses the current version of the Tor
|
||||
// server and determines whether it supports creationg v3 onion services through
|
||||
// Tor's control port. The version string should be of the format:
|
||||
// major.minor.revision.build
|
||||
func supportsV3(version string) error {
|
||||
// We'll split the minimum Tor version that's supported and the given
|
||||
// version in order to individually compare each number.
|
||||
parts := strings.Split(version, ".")
|
||||
if len(parts) != 4 {
|
||||
return errors.New("version string is not of the format " +
|
||||
"major.minor.revision.build")
|
||||
}
|
||||
|
||||
// It's possible that the build number (the last part of the version
|
||||
// string) includes a pre-release string, e.g. rc, beta, etc., so we'll
|
||||
// parse that as well.
|
||||
build := strings.Split(parts[len(parts)-1], "-")
|
||||
parts[len(parts)-1] = build[0]
|
||||
|
||||
// Ensure that each part of the version string corresponds to a number.
|
||||
for _, part := range parts {
|
||||
if _, err := strconv.Atoi(part); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Once we've determined we have a proper version string of the format
|
||||
// major.minor.revision.build, we can just do a string comparison to
|
||||
// determine if it satisfies the minimum version supported.
|
||||
if version < MinTorVersion {
|
||||
return fmt.Errorf("version %v below minimum version supported "+
|
||||
"%v", version, MinTorVersion)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ProtocolInfo returns the different authentication methods supported by the
|
||||
// Tor server and the version of the Tor server.
|
||||
func (c *Controller) ProtocolInfo() ([]string, string, string, error) {
|
||||
// We'll start off by sending the "PROTOCOLINFO" command to the Tor
|
||||
// server. We should receive a reply of the following format:
|
||||
//
|
||||
// METHODS=COOKIE,SAFECOOKIE
|
||||
// COOKIEFILE="/home/user/.tor/control_auth_cookie"
|
||||
// VERSION Tor="0.3.2.10"
|
||||
//
|
||||
// We're interested in retrieving all of these fields, so we'll parse
|
||||
// our reply to do so.
|
||||
cmd := fmt.Sprintf("PROTOCOLINFO %d", ProtocolInfoVersion)
|
||||
_, reply, err := c.sendCommand(cmd)
|
||||
if err != nil {
|
||||
return nil, "", "", err
|
||||
}
|
||||
|
||||
info := parseTorReply(reply)
|
||||
methods, ok := info["METHODS"]
|
||||
if !ok {
|
||||
return nil, "", "", errors.New("auth methods not found in " +
|
||||
"reply")
|
||||
}
|
||||
|
||||
cookieFile, ok := info["COOKIEFILE"]
|
||||
if !ok && !strings.Contains(methods, "NULL") {
|
||||
return nil, "", "", errors.New("cookie file path not found " +
|
||||
"in reply")
|
||||
}
|
||||
|
||||
version, ok := info["Tor"]
|
||||
if !ok {
|
||||
return nil, "", "", errors.New("Tor version not found in reply")
|
||||
}
|
||||
|
||||
// Finally, we'll clean up the results before returning them.
|
||||
authMethods := strings.Split(methods, ",")
|
||||
cookieFilePath := strings.Trim(cookieFile, "\"")
|
||||
torVersion := strings.Trim(version, "\"")
|
||||
|
||||
return authMethods, cookieFilePath, torVersion, nil
|
||||
}
|
||||
|
||||
// OnionType denotes the type of the onion service.
|
||||
type OnionType int
|
||||
|
||||
const (
|
||||
// V2 denotes that the onion service is V2.
|
||||
V2 OnionType = iota
|
||||
|
||||
// V3 denotes that the onion service is V3.
|
||||
V3
|
||||
)
|
||||
|
||||
// AddOnionConfig houses all of the required parameters in order to successfully
|
||||
// create a new onion service or restore an existing one.
|
||||
type AddOnionConfig struct {
|
||||
// Type denotes the type of the onion service that should be created.
|
||||
Type OnionType
|
||||
|
||||
// VirtualPort is the externally reachable port of the onion address.
|
||||
VirtualPort int
|
||||
|
||||
// TargetPorts is the set of ports that the service will be listening on
|
||||
// locally. The Tor server will use choose a random port from this set
|
||||
// to forward the traffic from the virtual port.
|
||||
//
|
||||
// NOTE: If nil/empty, the virtual port will be used as the only target
|
||||
// port.
|
||||
TargetPorts []int
|
||||
|
||||
// PrivateKeyPath is the full path to where the onion service's private
|
||||
// key is stored. This can be used to restore an existing onion service.
|
||||
PrivateKeyPath string
|
||||
}
|
||||
|
||||
// AddOnion creates an onion service and returns its onion address. Once
|
||||
// created, the new onion service will remain active until the connection
|
||||
// between the controller and the Tor server is closed.
|
||||
func (c *Controller) AddOnion(cfg AddOnionConfig) (*OnionAddr, error) {
|
||||
// Before sending the request to create an onion service to the Tor
|
||||
// server, we'll make sure that it supports V3 onion services if that
|
||||
// was the type requested.
|
||||
if cfg.Type == V3 {
|
||||
if err := supportsV3(c.version); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// We'll start off by checking if the file containing the private key
|
||||
// exists. If it does not, then we should request the server to create
|
||||
// a new onion service and return its private key. Otherwise, we'll
|
||||
// request the server to recreate the onion server from our private key.
|
||||
var keyParam string
|
||||
if _, err := os.Stat(cfg.PrivateKeyPath); os.IsNotExist(err) {
|
||||
switch cfg.Type {
|
||||
case V2:
|
||||
keyParam = "NEW:RSA1024"
|
||||
case V3:
|
||||
keyParam = "NEW:ED25519-V3"
|
||||
}
|
||||
} else {
|
||||
privateKey, err := ioutil.ReadFile(cfg.PrivateKeyPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
keyParam = string(privateKey)
|
||||
}
|
||||
|
||||
// Now, we'll create a mapping from the virtual port to each target
|
||||
// port. If no target ports were specified, we'll use the virtual port
|
||||
// to provide a one-to-one mapping.
|
||||
var portParam string
|
||||
if len(cfg.TargetPorts) == 0 {
|
||||
portParam += fmt.Sprintf("Port=%d,%d ", cfg.VirtualPort,
|
||||
cfg.VirtualPort)
|
||||
} else {
|
||||
for _, targetPort := range cfg.TargetPorts {
|
||||
portParam += fmt.Sprintf("Port=%d,%d ", cfg.VirtualPort,
|
||||
targetPort)
|
||||
}
|
||||
}
|
||||
|
||||
// Send the command to create the onion service to the Tor server and
|
||||
// await its response.
|
||||
cmd := fmt.Sprintf("ADD_ONION %s %s", keyParam, portParam)
|
||||
_, reply, err := c.sendCommand(cmd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If successful, the reply from the server should be of the following
|
||||
// format, depending on whether a private key has been requested:
|
||||
//
|
||||
// C: ADD_ONION RSA1024:[Blob Redacted] Port=80,8080
|
||||
// S: 250-ServiceID=testonion1234567
|
||||
// S: 250 OK
|
||||
//
|
||||
// C: ADD_ONION NEW:RSA1024 Port=80,8080
|
||||
// S: 250-ServiceID=testonion1234567
|
||||
// S: 250-PrivateKey=RSA1024:[Blob Redacted]
|
||||
// S: 250 OK
|
||||
//
|
||||
// We're interested in retrieving the service ID, which is the public
|
||||
// name of the service, and the private key if requested.
|
||||
replyParams := parseTorReply(reply)
|
||||
serviceID, ok := replyParams["ServiceID"]
|
||||
if !ok {
|
||||
return nil, errors.New("service id not found in reply")
|
||||
}
|
||||
|
||||
// If a new onion service was created, we'll write its private key to
|
||||
// disk under strict permissions in the event that it needs to be
|
||||
// recreated later on.
|
||||
if privateKey, ok := replyParams["PrivateKey"]; ok {
|
||||
err := ioutil.WriteFile(
|
||||
cfg.PrivateKeyPath, []byte(privateKey), 0600,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to write private key "+
|
||||
"to file: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, we'll return the onion address composed of the service ID,
|
||||
// along with the onion suffix, and the port this onion service can be
|
||||
// reached at externally.
|
||||
return &OnionAddr{
|
||||
OnionService: serviceID + ".onion",
|
||||
Port: cfg.VirtualPort,
|
||||
}, nil
|
||||
}
|
||||
104
vendor/github.com/lightningnetwork/lnd/tor/net.go
generated
vendored
Normal file
104
vendor/github.com/lightningnetwork/lnd/tor/net.go
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
package tor
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
)
|
||||
|
||||
// TODO: this interface and its implementations should ideally be moved
|
||||
// elsewhere as they are not Tor-specific.
|
||||
|
||||
// Net is an interface housing a Dial function and several DNS functions that
|
||||
// allows us to abstract the implementations of these functions over different
|
||||
// networks, e.g. clearnet, Tor net, etc.
|
||||
type Net interface {
|
||||
// Dial connects to the address on the named network.
|
||||
Dial(network, address string) (net.Conn, error)
|
||||
|
||||
// LookupHost performs DNS resolution on a given host and returns its
|
||||
// addresses.
|
||||
LookupHost(host string) ([]string, error)
|
||||
|
||||
// LookupSRV tries to resolve an SRV query of the given service,
|
||||
// protocol, and domain name.
|
||||
LookupSRV(service, proto, name string) (string, []*net.SRV, error)
|
||||
|
||||
// ResolveTCPAddr resolves TCP addresses.
|
||||
ResolveTCPAddr(network, address string) (*net.TCPAddr, error)
|
||||
}
|
||||
|
||||
// ClearNet is an implementation of the Net interface that defines behaviour
|
||||
// for regular network connections.
|
||||
type ClearNet struct{}
|
||||
|
||||
// Dial on the regular network uses net.Dial
|
||||
func (r *ClearNet) Dial(network, address string) (net.Conn, error) {
|
||||
return net.Dial(network, address)
|
||||
}
|
||||
|
||||
// LookupHost for regular network uses the net.LookupHost function
|
||||
func (r *ClearNet) LookupHost(host string) ([]string, error) {
|
||||
return net.LookupHost(host)
|
||||
}
|
||||
|
||||
// LookupSRV for regular network uses net.LookupSRV function
|
||||
func (r *ClearNet) LookupSRV(service, proto, name string) (string, []*net.SRV, error) {
|
||||
return net.LookupSRV(service, proto, name)
|
||||
}
|
||||
|
||||
// ResolveTCPAddr for regular network uses net.ResolveTCPAddr function
|
||||
func (r *ClearNet) ResolveTCPAddr(network, address string) (*net.TCPAddr, error) {
|
||||
return net.ResolveTCPAddr(network, address)
|
||||
}
|
||||
|
||||
// ProxyNet is an implementation of the Net interface that defines behaviour
|
||||
// for Tor network connections.
|
||||
type ProxyNet struct {
|
||||
// SOCKS is the host:port which Tor's exposed SOCKS5 proxy is listening
|
||||
// on.
|
||||
SOCKS string
|
||||
|
||||
// DNS is the host:port of the DNS server for Tor to use for SRV
|
||||
// queries.
|
||||
DNS string
|
||||
|
||||
// StreamIsolation is a bool that determines if we should force the
|
||||
// creation of a new circuit for this connection. If true, then this
|
||||
// means that our traffic may be harder to correlate as each connection
|
||||
// will now use a distinct circuit.
|
||||
StreamIsolation bool
|
||||
}
|
||||
|
||||
// Dial uses the Tor Dial function in order to establish connections through
|
||||
// Tor. Since Tor only supports TCP connections, only TCP networks are allowed.
|
||||
func (p *ProxyNet) Dial(network, address string) (net.Conn, error) {
|
||||
switch network {
|
||||
case "tcp", "tcp4", "tcp6":
|
||||
default:
|
||||
return nil, errors.New("cannot dial non-tcp network via Tor")
|
||||
}
|
||||
return Dial(address, p.SOCKS, p.StreamIsolation)
|
||||
}
|
||||
|
||||
// LookupHost uses the Tor LookupHost function in order to resolve hosts over
|
||||
// Tor.
|
||||
func (p *ProxyNet) LookupHost(host string) ([]string, error) {
|
||||
return LookupHost(host, p.SOCKS)
|
||||
}
|
||||
|
||||
// LookupSRV uses the Tor LookupSRV function in order to resolve SRV DNS queries
|
||||
// over Tor.
|
||||
func (p *ProxyNet) LookupSRV(service, proto, name string) (string, []*net.SRV, error) {
|
||||
return LookupSRV(service, proto, name, p.SOCKS, p.DNS, p.StreamIsolation)
|
||||
}
|
||||
|
||||
// ResolveTCPAddr uses the Tor ResolveTCPAddr function in order to resolve TCP
|
||||
// addresses over Tor.
|
||||
func (p *ProxyNet) ResolveTCPAddr(network, address string) (*net.TCPAddr, error) {
|
||||
switch network {
|
||||
case "tcp", "tcp4", "tcp6":
|
||||
default:
|
||||
return nil, errors.New("cannot dial non-tcp network via Tor")
|
||||
}
|
||||
return ResolveTCPAddr(address, p.SOCKS)
|
||||
}
|
||||
63
vendor/github.com/lightningnetwork/lnd/tor/onionaddr.go
generated
vendored
Normal file
63
vendor/github.com/lightningnetwork/lnd/tor/onionaddr.go
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
package tor
|
||||
|
||||
import (
|
||||
"encoding/base32"
|
||||
"net"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
// base32Alphabet is the alphabet used for encoding and decoding v2 and
|
||||
// v3 onion addresses.
|
||||
base32Alphabet = "abcdefghijklmnopqrstuvwxyz234567"
|
||||
|
||||
// OnionSuffix is the ".onion" suffix for v2 and v3 onion addresses.
|
||||
OnionSuffix = ".onion"
|
||||
|
||||
// OnionSuffixLen is the length of the ".onion" suffix.
|
||||
OnionSuffixLen = len(OnionSuffix)
|
||||
|
||||
// V2DecodedLen is the length of a decoded v2 onion service.
|
||||
V2DecodedLen = 10
|
||||
|
||||
// V2Len is the length of a v2 onion service including the ".onion"
|
||||
// suffix.
|
||||
V2Len = 22
|
||||
|
||||
// V3DecodedLen is the length of a decoded v3 onion service.
|
||||
V3DecodedLen = 35
|
||||
|
||||
// V3Len is the length of a v2 onion service including the ".onion"
|
||||
// suffix.
|
||||
V3Len = 62
|
||||
)
|
||||
|
||||
var (
|
||||
// Base32Encoding represents the Tor's base32-encoding scheme for v2 and
|
||||
// v3 onion addresses.
|
||||
Base32Encoding = base32.NewEncoding(base32Alphabet)
|
||||
)
|
||||
|
||||
// OnionAddr represents a Tor network end point onion address.
|
||||
type OnionAddr struct {
|
||||
// OnionService is the host of the onion address.
|
||||
OnionService string
|
||||
|
||||
// Port is the port of the onion address.
|
||||
Port int
|
||||
}
|
||||
|
||||
// A compile-time check to ensure that OnionAddr implements the net.Addr
|
||||
// interface.
|
||||
var _ net.Addr = (*OnionAddr)(nil)
|
||||
|
||||
// String returns the string representation of an onion address.
|
||||
func (o *OnionAddr) String() string {
|
||||
return net.JoinHostPort(o.OnionService, strconv.Itoa(o.Port))
|
||||
}
|
||||
|
||||
// Network returns the network that this implementation of net.Addr will use.
|
||||
// In this case, because Tor only allows TCP connections, the network is "tcp".
|
||||
func (o *OnionAddr) Network() string {
|
||||
return "tcp"
|
||||
}
|
||||
243
vendor/github.com/lightningnetwork/lnd/tor/tor.go
generated
vendored
Normal file
243
vendor/github.com/lightningnetwork/lnd/tor/tor.go
generated
vendored
Normal file
@@ -0,0 +1,243 @@
|
||||
package tor
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
|
||||
"github.com/btcsuite/btcd/connmgr"
|
||||
"github.com/miekg/dns"
|
||||
"golang.org/x/net/proxy"
|
||||
)
|
||||
|
||||
var (
|
||||
// dnsCodes maps the DNS response codes to a friendly description. This
|
||||
// does not include the BADVERS code because of duplicate keys and the
|
||||
// underlying DNS (miekg/dns) package not using it. For more info, see
|
||||
// https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml.
|
||||
dnsCodes = map[int]string{
|
||||
0: "no error",
|
||||
1: "format error",
|
||||
2: "server failure",
|
||||
3: "non-existent domain",
|
||||
4: "not implemented",
|
||||
5: "query refused",
|
||||
6: "name exists when it should not",
|
||||
7: "RR set exists when it should not",
|
||||
8: "RR set that should exist does not",
|
||||
9: "server not authoritative for zone",
|
||||
10: "name not contained in zone",
|
||||
16: "TSIG signature failure",
|
||||
17: "key not recognized",
|
||||
18: "signature out of time window",
|
||||
19: "bad TKEY mode",
|
||||
20: "duplicate key name",
|
||||
21: "algorithm not supported",
|
||||
22: "bad truncation",
|
||||
23: "bad/missing server cookie",
|
||||
}
|
||||
)
|
||||
|
||||
// proxyConn is a wrapper around net.Conn that allows us to expose the actual
|
||||
// remote address we're dialing, rather than the proxy's address.
|
||||
type proxyConn struct {
|
||||
net.Conn
|
||||
remoteAddr net.Addr
|
||||
}
|
||||
|
||||
func (c *proxyConn) RemoteAddr() net.Addr {
|
||||
return c.remoteAddr
|
||||
}
|
||||
|
||||
// Dial is a wrapper over the non-exported dial function that returns a wrapper
|
||||
// around net.Conn in order to expose the actual remote address we're dialing,
|
||||
// rather than the proxy's address.
|
||||
func Dial(address, socksAddr string, streamIsolation bool) (net.Conn, error) {
|
||||
conn, err := dial(address, socksAddr, streamIsolation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Now that the connection is established, we'll create our internal
|
||||
// proxyConn that will serve in populating the correct remote address
|
||||
// of the connection, rather than using the proxy's address.
|
||||
remoteAddr, err := ParseAddr(address, socksAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &proxyConn{
|
||||
Conn: conn,
|
||||
remoteAddr: remoteAddr,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// dial establishes a connection to the address via Tor's SOCKS proxy. Only TCP
|
||||
// is supported over Tor. The final argument determines if we should force
|
||||
// stream isolation for this new connection. If we do, then this means this new
|
||||
// connection will use a fresh circuit, rather than possibly re-using an
|
||||
// existing circuit.
|
||||
func dial(address, socksAddr string, streamIsolation bool) (net.Conn, error) {
|
||||
// If we were requested to force stream isolation for this connection,
|
||||
// we'll populate the authentication credentials with random data as
|
||||
// Tor will create a new circuit for each set of credentials.
|
||||
var auth *proxy.Auth
|
||||
if streamIsolation {
|
||||
var b [16]byte
|
||||
if _, err := rand.Read(b[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
auth = &proxy.Auth{
|
||||
User: hex.EncodeToString(b[:8]),
|
||||
Password: hex.EncodeToString(b[8:]),
|
||||
}
|
||||
}
|
||||
|
||||
// Establish the connection through Tor's SOCKS proxy.
|
||||
dialer, err := proxy.SOCKS5("tcp", socksAddr, auth, proxy.Direct)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return dialer.Dial("tcp", address)
|
||||
}
|
||||
|
||||
// LookupHost performs DNS resolution on a given host via Tor's native resolver.
|
||||
// Only IPv4 addresses are returned.
|
||||
func LookupHost(host, socksAddr string) ([]string, error) {
|
||||
ip, err := connmgr.TorLookupIP(host, socksAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Only one IPv4 address is returned by the TorLookupIP function.
|
||||
return []string{ip[0].String()}, nil
|
||||
}
|
||||
|
||||
// LookupSRV uses Tor's SOCKS proxy to route DNS SRV queries. Tor does not
|
||||
// natively support SRV queries so we must route all SRV queries through the
|
||||
// proxy by connecting directly to a DNS server and querying it. The DNS server
|
||||
// must have TCP resolution enabled for the given port.
|
||||
func LookupSRV(service, proto, name, socksAddr, dnsServer string,
|
||||
streamIsolation bool) (string, []*net.SRV, error) {
|
||||
|
||||
// Connect to the DNS server we'll be using to query SRV records.
|
||||
conn, err := dial(dnsServer, socksAddr, streamIsolation)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
dnsConn := &dns.Conn{Conn: conn}
|
||||
defer dnsConn.Close()
|
||||
|
||||
// Once connected, we'll construct the SRV request for the host
|
||||
// following the format _service._proto.name. as described in RFC #2782.
|
||||
host := fmt.Sprintf("_%s._%s.%s.", service, proto, name)
|
||||
msg := new(dns.Msg).SetQuestion(host, dns.TypeSRV)
|
||||
|
||||
// Send the request to the DNS server and read its response.
|
||||
if err := dnsConn.WriteMsg(msg); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
resp, err := dnsConn.ReadMsg()
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
// We'll fail if we were unable to query the DNS server for our record.
|
||||
if resp.Rcode != dns.RcodeSuccess {
|
||||
return "", nil, fmt.Errorf("unable to query for SRV records: "+
|
||||
"%s", dnsCodes[resp.Rcode])
|
||||
}
|
||||
|
||||
// Retrieve the RR(s) of the Answer section.
|
||||
var rrs []*net.SRV
|
||||
for _, rr := range resp.Answer {
|
||||
srv := rr.(*dns.SRV)
|
||||
rrs = append(rrs, &net.SRV{
|
||||
Target: srv.Target,
|
||||
Port: srv.Port,
|
||||
Priority: srv.Priority,
|
||||
Weight: srv.Weight,
|
||||
})
|
||||
}
|
||||
|
||||
return "", rrs, nil
|
||||
}
|
||||
|
||||
// ResolveTCPAddr uses Tor's proxy to resolve TCP addresses instead of the
|
||||
// standard system resolver provided in the `net` package.
|
||||
func ResolveTCPAddr(address, socksAddr string) (*net.TCPAddr, error) {
|
||||
// Split host:port since the lookup function does not take a port.
|
||||
host, port, err := net.SplitHostPort(address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ip, err := LookupHost(host, socksAddr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
p, err := strconv.Atoi(port)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &net.TCPAddr{
|
||||
IP: net.ParseIP(ip[0]),
|
||||
Port: p,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ParseAddr parses an address from its string format to a net.Addr.
|
||||
func ParseAddr(address, socksAddr string) (net.Addr, error) {
|
||||
host, portStr, err := net.SplitHostPort(address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
port, err := strconv.Atoi(portStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if IsOnionHost(host) {
|
||||
return &OnionAddr{OnionService: host, Port: port}, nil
|
||||
}
|
||||
|
||||
return ResolveTCPAddr(address, socksAddr)
|
||||
}
|
||||
|
||||
// IsOnionHost determines whether a host is part of an onion address.
|
||||
func IsOnionHost(host string) bool {
|
||||
// Note the starting index of the onion suffix in the host depending
|
||||
// on its length.
|
||||
var suffixIndex int
|
||||
switch len(host) {
|
||||
case V2Len:
|
||||
suffixIndex = V2Len - OnionSuffixLen
|
||||
case V3Len:
|
||||
suffixIndex = V3Len - OnionSuffixLen
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
// Make sure the host ends with the ".onion" suffix.
|
||||
if host[suffixIndex:] != OnionSuffix {
|
||||
return false
|
||||
}
|
||||
|
||||
// We'll now attempt to decode the host without its suffix, as the
|
||||
// suffix includes invalid characters. This will tell us if the host is
|
||||
// actually valid if successful.
|
||||
host = host[:suffixIndex]
|
||||
if _, err := Base32Encoding.DecodeString(host); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
22
vendor/github.com/lightningnetwork/lnd/zpay32/README.md
generated
vendored
Normal file
22
vendor/github.com/lightningnetwork/lnd/zpay32/README.md
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
zpay32
|
||||
=======
|
||||
|
||||
[](https://travis-ci.org/lightningnetwork/lnd)
|
||||
[](https://github.com/lightningnetwork/lnd/blob/master/LICENSE)
|
||||
[](http://godoc.org/github.com/lightningnetwork/lnd/zpay32)
|
||||
|
||||
The zpay32 package implements a basic scheme for the encoding of payment
|
||||
requests between two `lnd` nodes within the Lightning Network. The zpay32
|
||||
encoding scheme uses the
|
||||
[zbase32](https://philzimmermann.com/docs/human-oriented-base-32-encoding.txt)
|
||||
scheme along with a checksum to encode a serialized payment request.
|
||||
|
||||
The payment request serialized by the package consist of: the destination's
|
||||
public key, the payment hash to use for the payment, and the value of payment
|
||||
to send.
|
||||
|
||||
## Installation and Updating
|
||||
|
||||
```bash
|
||||
$ go get -u github.com/lightningnetwork/lnd/zpay32
|
||||
```
|
||||
162
vendor/github.com/lightningnetwork/lnd/zpay32/amountunits.go
generated
vendored
Normal file
162
vendor/github.com/lightningnetwork/lnd/zpay32/amountunits.go
generated
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
package zpay32
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
)
|
||||
|
||||
var (
|
||||
// toMSat is a map from a unit to a function that converts an amount
|
||||
// of that unit to millisatoshis.
|
||||
toMSat = map[byte]func(uint64) (lnwire.MilliSatoshi, error){
|
||||
'm': mBtcToMSat,
|
||||
'u': uBtcToMSat,
|
||||
'n': nBtcToMSat,
|
||||
'p': pBtcToMSat,
|
||||
}
|
||||
|
||||
// fromMSat is a map from a unit to a function that converts an amount
|
||||
// in millisatoshis to an amount of that unit.
|
||||
fromMSat = map[byte]func(lnwire.MilliSatoshi) (uint64, error){
|
||||
'm': mSatToMBtc,
|
||||
'u': mSatToUBtc,
|
||||
'n': mSatToNBtc,
|
||||
'p': mSatToPBtc,
|
||||
}
|
||||
)
|
||||
|
||||
// mBtcToMSat converts the given amount in milliBTC to millisatoshis.
|
||||
func mBtcToMSat(m uint64) (lnwire.MilliSatoshi, error) {
|
||||
return lnwire.MilliSatoshi(m) * 100000000, nil
|
||||
}
|
||||
|
||||
// uBtcToMSat converts the given amount in microBTC to millisatoshis.
|
||||
func uBtcToMSat(u uint64) (lnwire.MilliSatoshi, error) {
|
||||
return lnwire.MilliSatoshi(u * 100000), nil
|
||||
}
|
||||
|
||||
// nBtcToMSat converts the given amount in nanoBTC to millisatoshis.
|
||||
func nBtcToMSat(n uint64) (lnwire.MilliSatoshi, error) {
|
||||
return lnwire.MilliSatoshi(n * 100), nil
|
||||
}
|
||||
|
||||
// pBtcToMSat converts the given amount in picoBTC to millisatoshis.
|
||||
func pBtcToMSat(p uint64) (lnwire.MilliSatoshi, error) {
|
||||
if p < 10 {
|
||||
return 0, fmt.Errorf("minimum amount is 10p")
|
||||
}
|
||||
if p%10 != 0 {
|
||||
return 0, fmt.Errorf("amount %d pBTC not expressible in msat",
|
||||
p)
|
||||
}
|
||||
return lnwire.MilliSatoshi(p / 10), nil
|
||||
}
|
||||
|
||||
// mSatToMBtc converts the given amount in millisatoshis to milliBTC.
|
||||
func mSatToMBtc(msat lnwire.MilliSatoshi) (uint64, error) {
|
||||
if msat%100000000 != 0 {
|
||||
return 0, fmt.Errorf("%d msat not expressible "+
|
||||
"in mBTC", msat)
|
||||
}
|
||||
return uint64(msat / 100000000), nil
|
||||
}
|
||||
|
||||
// mSatToUBtc converts the given amount in millisatoshis to microBTC.
|
||||
func mSatToUBtc(msat lnwire.MilliSatoshi) (uint64, error) {
|
||||
if msat%100000 != 0 {
|
||||
return 0, fmt.Errorf("%d msat not expressible "+
|
||||
"in uBTC", msat)
|
||||
}
|
||||
return uint64(msat / 100000), nil
|
||||
}
|
||||
|
||||
// mSatToNBtc converts the given amount in millisatoshis to nanoBTC.
|
||||
func mSatToNBtc(msat lnwire.MilliSatoshi) (uint64, error) {
|
||||
if msat%100 != 0 {
|
||||
return 0, fmt.Errorf("%d msat not expressible in nBTC", msat)
|
||||
}
|
||||
return uint64(msat / 100), nil
|
||||
}
|
||||
|
||||
// mSatToPBtc converts the given amount in millisatoshis to picoBTC.
|
||||
func mSatToPBtc(msat lnwire.MilliSatoshi) (uint64, error) {
|
||||
return uint64(msat * 10), nil
|
||||
}
|
||||
|
||||
// decodeAmount returns the amount encoded by the provided string in
|
||||
// millisatoshi.
|
||||
func decodeAmount(amount string) (lnwire.MilliSatoshi, error) {
|
||||
if len(amount) < 1 {
|
||||
return 0, fmt.Errorf("amount must be non-empty")
|
||||
}
|
||||
|
||||
// If last character is a digit, then the amount can just be
|
||||
// interpreted as BTC.
|
||||
char := amount[len(amount)-1]
|
||||
digit := char - '0'
|
||||
if digit >= 0 && digit <= 9 {
|
||||
btc, err := strconv.ParseUint(amount, 10, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return lnwire.MilliSatoshi(btc) * mSatPerBtc, nil
|
||||
}
|
||||
|
||||
// If not a digit, it must be part of the known units.
|
||||
conv, ok := toMSat[char]
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("unknown multiplier %c", char)
|
||||
}
|
||||
|
||||
// Known unit.
|
||||
num := amount[:len(amount)-1]
|
||||
if len(num) < 1 {
|
||||
return 0, fmt.Errorf("number must be non-empty")
|
||||
}
|
||||
|
||||
am, err := strconv.ParseUint(num, 10, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return conv(am)
|
||||
}
|
||||
|
||||
// encodeAmount encodes the provided millisatoshi amount using as few characters
|
||||
// as possible.
|
||||
func encodeAmount(msat lnwire.MilliSatoshi) (string, error) {
|
||||
if msat < 0 {
|
||||
return "", fmt.Errorf("amount must be positive: %v", msat)
|
||||
}
|
||||
|
||||
// If possible to express in BTC, that will always be the shortest
|
||||
// representation.
|
||||
if msat%mSatPerBtc == 0 {
|
||||
return strconv.FormatInt(int64(msat/mSatPerBtc), 10), nil
|
||||
}
|
||||
|
||||
// Should always be expressible in pico BTC.
|
||||
pico, err := fromMSat['p'](msat)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("unable to express %d msat as pBTC: %v",
|
||||
msat, err)
|
||||
}
|
||||
shortened := strconv.FormatUint(pico, 10) + "p"
|
||||
for unit, conv := range fromMSat {
|
||||
am, err := conv(msat)
|
||||
if err != nil {
|
||||
// Not expressible using this unit.
|
||||
continue
|
||||
}
|
||||
|
||||
// Save the shortest found representation.
|
||||
str := strconv.FormatUint(am, 10) + string(unit)
|
||||
if len(str) < len(shortened) {
|
||||
shortened = str
|
||||
}
|
||||
}
|
||||
|
||||
return shortened, nil
|
||||
}
|
||||
168
vendor/github.com/lightningnetwork/lnd/zpay32/bech32.go
generated
vendored
Normal file
168
vendor/github.com/lightningnetwork/lnd/zpay32/bech32.go
generated
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
package zpay32
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const charset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
|
||||
|
||||
var gen = []int{0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3}
|
||||
|
||||
// NOTE: This method it a slight modification of the method bech32.Decode found
|
||||
// btcutil, allowing strings to be more than 90 characters.
|
||||
|
||||
// decodeBech32 decodes a bech32 encoded string, returning the human-readable
|
||||
// part and the data part excluding the checksum.
|
||||
// Note: the data will be base32 encoded, that is each element of the returned
|
||||
// byte array will encode 5 bits of data. Use the ConvertBits method to convert
|
||||
// this to 8-bit representation.
|
||||
func decodeBech32(bech string) (string, []byte, error) {
|
||||
// The maximum allowed length for a bech32 string is 90. It must also
|
||||
// be at least 8 characters, since it needs a non-empty HRP, a
|
||||
// separator, and a 6 character checksum.
|
||||
// NB: The 90 character check specified in BIP173 is skipped here, to
|
||||
// allow strings longer than 90 characters.
|
||||
if len(bech) < 8 {
|
||||
return "", nil, fmt.Errorf("invalid bech32 string length %d",
|
||||
len(bech))
|
||||
}
|
||||
// Only ASCII characters between 33 and 126 are allowed.
|
||||
for i := 0; i < len(bech); i++ {
|
||||
if bech[i] < 33 || bech[i] > 126 {
|
||||
return "", nil, fmt.Errorf("invalid character in "+
|
||||
"string: '%c'", bech[i])
|
||||
}
|
||||
}
|
||||
|
||||
// The characters must be either all lowercase or all uppercase.
|
||||
lower := strings.ToLower(bech)
|
||||
upper := strings.ToUpper(bech)
|
||||
if bech != lower && bech != upper {
|
||||
return "", nil, fmt.Errorf("string not all lowercase or all " +
|
||||
"uppercase")
|
||||
}
|
||||
|
||||
// We'll work with the lowercase string from now on.
|
||||
bech = lower
|
||||
|
||||
// The string is invalid if the last '1' is non-existent, it is the
|
||||
// first character of the string (no human-readable part) or one of the
|
||||
// last 6 characters of the string (since checksum cannot contain '1'),
|
||||
// or if the string is more than 90 characters in total.
|
||||
one := strings.LastIndexByte(bech, '1')
|
||||
if one < 1 || one+7 > len(bech) {
|
||||
return "", nil, fmt.Errorf("invalid index of 1")
|
||||
}
|
||||
|
||||
// The human-readable part is everything before the last '1'.
|
||||
hrp := bech[:one]
|
||||
data := bech[one+1:]
|
||||
|
||||
// Each character corresponds to the byte with value of the index in
|
||||
// 'charset'.
|
||||
decoded, err := toBytes(data)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("failed converting data to bytes: "+
|
||||
"%v", err)
|
||||
}
|
||||
|
||||
if !bech32VerifyChecksum(hrp, decoded) {
|
||||
moreInfo := ""
|
||||
checksum := bech[len(bech)-6:]
|
||||
expected, err := toChars(bech32Checksum(hrp,
|
||||
decoded[:len(decoded)-6]))
|
||||
if err == nil {
|
||||
moreInfo = fmt.Sprintf("Expected %v, got %v.",
|
||||
expected, checksum)
|
||||
}
|
||||
return "", nil, fmt.Errorf("checksum failed. " + moreInfo)
|
||||
}
|
||||
|
||||
// We exclude the last 6 bytes, which is the checksum.
|
||||
return hrp, decoded[:len(decoded)-6], nil
|
||||
}
|
||||
|
||||
// toBytes converts each character in the string 'chars' to the value of the
|
||||
// index of the corresponding character in 'charset'.
|
||||
func toBytes(chars string) ([]byte, error) {
|
||||
decoded := make([]byte, 0, len(chars))
|
||||
for i := 0; i < len(chars); i++ {
|
||||
index := strings.IndexByte(charset, chars[i])
|
||||
if index < 0 {
|
||||
return nil, fmt.Errorf("invalid character not part of "+
|
||||
"charset: %v", chars[i])
|
||||
}
|
||||
decoded = append(decoded, byte(index))
|
||||
}
|
||||
return decoded, nil
|
||||
}
|
||||
|
||||
// toChars converts the byte slice 'data' to a string where each byte in 'data'
|
||||
// encodes the index of a character in 'charset'.
|
||||
func toChars(data []byte) (string, error) {
|
||||
result := make([]byte, 0, len(data))
|
||||
for _, b := range data {
|
||||
if int(b) >= len(charset) {
|
||||
return "", fmt.Errorf("invalid data byte: %v", b)
|
||||
}
|
||||
result = append(result, charset[b])
|
||||
}
|
||||
return string(result), nil
|
||||
}
|
||||
|
||||
// For more details on the checksum calculation, please refer to BIP 173.
|
||||
func bech32Checksum(hrp string, data []byte) []byte {
|
||||
// Convert the bytes to list of integers, as this is needed for the
|
||||
// checksum calculation.
|
||||
integers := make([]int, len(data))
|
||||
for i, b := range data {
|
||||
integers[i] = int(b)
|
||||
}
|
||||
values := append(bech32HrpExpand(hrp), integers...)
|
||||
values = append(values, []int{0, 0, 0, 0, 0, 0}...)
|
||||
polymod := bech32Polymod(values) ^ 1
|
||||
var res []byte
|
||||
for i := 0; i < 6; i++ {
|
||||
res = append(res, byte((polymod>>uint(5*(5-i)))&31))
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// For more details on the polymod calculation, please refer to BIP 173.
|
||||
func bech32Polymod(values []int) int {
|
||||
chk := 1
|
||||
for _, v := range values {
|
||||
b := chk >> 25
|
||||
chk = (chk&0x1ffffff)<<5 ^ v
|
||||
for i := 0; i < 5; i++ {
|
||||
if (b>>uint(i))&1 == 1 {
|
||||
chk ^= gen[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
return chk
|
||||
}
|
||||
|
||||
// For more details on HRP expansion, please refer to BIP 173.
|
||||
func bech32HrpExpand(hrp string) []int {
|
||||
v := make([]int, 0, len(hrp)*2+1)
|
||||
for i := 0; i < len(hrp); i++ {
|
||||
v = append(v, int(hrp[i]>>5))
|
||||
}
|
||||
v = append(v, 0)
|
||||
for i := 0; i < len(hrp); i++ {
|
||||
v = append(v, int(hrp[i]&31))
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// For more details on the checksum verification, please refer to BIP 173.
|
||||
func bech32VerifyChecksum(hrp string, data []byte) bool {
|
||||
integers := make([]int, len(data))
|
||||
for i, b := range data {
|
||||
integers[i] = int(b)
|
||||
}
|
||||
concat := append(bech32HrpExpand(hrp), integers...)
|
||||
return bech32Polymod(concat) == 1
|
||||
}
|
||||
43
vendor/github.com/lightningnetwork/lnd/zpay32/hophint.go
generated
vendored
Normal file
43
vendor/github.com/lightningnetwork/lnd/zpay32/hophint.go
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
package zpay32
|
||||
|
||||
import "github.com/btcsuite/btcd/btcec"
|
||||
|
||||
const (
|
||||
// DefaultFinalCLTVDelta is the default value to be used as the final
|
||||
// CLTV delta for a route if one is unspecified.
|
||||
DefaultFinalCLTVDelta = 9
|
||||
)
|
||||
|
||||
// HopHint is a routing hint that contains the minimum information of a channel
|
||||
// required for an intermediate hop in a route to forward the payment to the
|
||||
// next. This should be ideally used for private channels, since they are not
|
||||
// publicly advertised to the network for routing.
|
||||
type HopHint struct {
|
||||
// NodeID is the public key of the node at the start of the channel.
|
||||
NodeID *btcec.PublicKey
|
||||
|
||||
// ChannelID is the unique identifier of the channel.
|
||||
ChannelID uint64
|
||||
|
||||
// FeeBaseMSat is the base fee of the channel in millisatoshis.
|
||||
FeeBaseMSat uint32
|
||||
|
||||
// FeeProportionalMillionths is the fee rate, in millionths of a
|
||||
// satoshi, for every satoshi sent through the channel.
|
||||
FeeProportionalMillionths uint32
|
||||
|
||||
// CLTVExpiryDelta is the time-lock delta of the channel.
|
||||
CLTVExpiryDelta uint16
|
||||
}
|
||||
|
||||
// Copy returns a deep copy of the hop hint.
|
||||
func (h HopHint) Copy() HopHint {
|
||||
nodeID := *h.NodeID
|
||||
return HopHint{
|
||||
NodeID: &nodeID,
|
||||
ChannelID: h.ChannelID,
|
||||
FeeBaseMSat: h.FeeBaseMSat,
|
||||
FeeProportionalMillionths: h.FeeProportionalMillionths,
|
||||
CLTVExpiryDelta: h.CLTVExpiryDelta,
|
||||
}
|
||||
}
|
||||
1097
vendor/github.com/lightningnetwork/lnd/zpay32/invoice.go
generated
vendored
Normal file
1097
vendor/github.com/lightningnetwork/lnd/zpay32/invoice.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user