Documentation ¶
Index ¶
- Constants
- Variables
- func DisableLog()
- func UseLogger(logger btclog.Logger)
- type Batch
- type Circuit
- type Hash256
- type HashPrefix
- type HopData
- type MemoryReplayLog
- func (rl *MemoryReplayLog) Delete(hash *HashPrefix) error
- func (rl *MemoryReplayLog) Get(hash *HashPrefix) (uint32, error)
- func (rl *MemoryReplayLog) Put(hash *HashPrefix, cltv uint32) error
- func (rl *MemoryReplayLog) PutBatch(batch *Batch) (*ReplaySet, error)
- func (rl *MemoryReplayLog) Start() error
- func (rl *MemoryReplayLog) Stop() error
- type OnionErrorDecrypter
- type OnionErrorEncrypter
- type OnionPacket
- type ProcessCode
- type ProcessedPacket
- type ReplayLog
- type ReplaySet
- type Router
- func (r *Router) BeginTxn(id []byte, nels int) *Tx
- func (r *Router) ProcessOnionPacket(onionPkt *OnionPacket, assocData []byte, incomingCltv uint32) (*ProcessedPacket, error)
- func (r *Router) ReconstructOnionPacket(onionPkt *OnionPacket, assocData []byte) (*ProcessedPacket, error)
- func (r *Router) Start() error
- func (r *Router) Stop()
- type Tx
Constants ¶
const ( // ExitNode indicates that the node which processed the Sphinx packet // is the destination hop in the route. ExitNode = iota // MoreHops indicates that there are additional hops left within the // route. Therefore the caller should forward the packet to the node // denoted as the "NextHop". MoreHops // Failure indicates that a failure occurred during packet processing. Failure )
const ( // HashPrefixSize is the size in bytes of the keys we will be storing // in the ReplayLog. It represents the first 20 bytes of a truncated // sha-256 hash of a secret generated by ECDH. HashPrefixSize = 20 )
const ( // NumMaxHops is the the maximum path length. This should be set to an // estiamate of the upper limit of the diameter of the node graph. NumMaxHops = 20 )
Variables ¶
var ( // ErrReplayedPacket is an error returned when a packet is rejected // during processing due to being an attempted replay or probing // attempt. ErrReplayedPacket = fmt.Errorf("sphinx packet replay attempted") // ErrInvalidOnionVersion is returned during decoding of the onion // packet, when the received packet has an unknown version byte. ErrInvalidOnionVersion = fmt.Errorf("invalid onion packet version") // ErrInvalidOnionHMAC is returned during onion parsing process, when received // mac does not corresponds to the generated one. ErrInvalidOnionHMAC = fmt.Errorf("invalid mismatched mac") // ErrInvalidOnionKey is returned during onion parsing process, when // onion key is invalid. ErrInvalidOnionKey = fmt.Errorf("invalid onion key: pubkey isn't on " + "secp256k1 curve") // ErrLogEntryNotFound is an error returned when a packet lookup in a replay // log fails because it is missing. ErrLogEntryNotFound = fmt.Errorf("sphinx packet is not in log") )
var ErrAlreadyCommitted = errors.New("cannot add to batch after committing")
ErrAlreadyCommitted signals that an entry could not be added to the batch because it has already been persisted.
Functions ¶
func DisableLog ¶
func DisableLog()
DisableLog disables all library log output. Logging output is disabled by default until UseLogger is called.
Types ¶
type Batch ¶
type Batch struct { // IsCommitted denotes whether or not this batch has been successfully // written to disk. IsCommitted bool // ID is a unique, caller chosen identifier for this batch. ID []byte // ReplaySet contains the sequence numbers of all entries that were // detected as replays. The set is finalized upon writing the batch to // disk, and merges replays detected by the replay cache and on-disk // replay log. ReplaySet *ReplaySet // contains filtered or unexported fields }
Batch is an object used to incrementally construct a set of entries to add to the replay log. After construction is completed, it can be added to the log using the PutBatch method.
func NewBatch ¶
NewBatch initializes an object for constructing a set of entries to atomically add to a replay log. Batches are identified by byte slice, which allows the caller to safely process the same batch twice and get an idempotent result.
func (*Batch) ForEach ¶
ForEach iterates through each entry in the batch and calls the provided function with the sequence number and entry contents as arguments.
func (*Batch) Put ¶
func (b *Batch) Put(seqNum uint16, hashPrefix *HashPrefix, cltv uint32) error
Put inserts a hash-prefix/CLTV pair into the current batch. This method only returns an error in the event that the batch was already committed to disk. Decisions regarding whether or not a particular sequence number is a replay is ultimately reported via the batch's ReplaySet after committing to disk.
type Circuit ¶
type Circuit struct { // SessionKey is the key which have been used during generation of the // shared secrets. SessionKey *btcec.PrivateKey // PaymentPath is the pub keys of the nodes in the payment path. PaymentPath []*btcec.PublicKey }
Circuit is used encapsulate the data which is needed for data deobfuscation.
type Hash256 ¶
Hash256 is a statically sized, 32-byte array, typically containing the output of a SHA256 hash.
type HashPrefix ¶
type HashPrefix [HashPrefixSize]byte
HashPrefix is a statically size, 20-byte array containing the prefix of a Hash256, and is used to detect duplicate sphinx packets.
type HopData ¶
type HopData struct { // Realm denotes the "real" of target chain of the next hop. For // bitcoin, this value will be 0x00. Realm byte // NextAddress is the address of the next hop that this packet should // be forward to. NextAddress [addressSize]byte // ForwardAmount is the HTLC amount that the next hop should forward. // This value should take into account the fee require by this // particular hop, and the cumulative fee for the entire route. ForwardAmount uint64 // OutgoingCltv is the value of the outgoing absolute time-lock that // should be included in the HTLC forwarded. OutgoingCltv uint32 // ExtraBytes is the set of unused bytes within the onion payload. This // extra set of bytes can be utilized by higher level applications to // package additional data within the per-hop payload, or signal that a // portion of the remaining set of hops are to be consumed as Extra // Onion Blobs. ExtraBytes [padSize]byte // HMAC is an HMAC computed over the entire per-hop payload that also // includes the higher-level (optional) associated data bytes. HMAC [hmacSize]byte }
HopData is the information destined for individual hops. It is a fixed size 64 bytes, prefixed with a 1 byte realm that indicates how to interpret it. For now we simply assume it's the bitcoin realm (0x00) and hence the format is fixed. The last 32 bytes are always the HMAC to be passed to the next hop, or zero if this is the packet is not to be forwarded, since this is the last hop.
type MemoryReplayLog ¶
type MemoryReplayLog struct {
// contains filtered or unexported fields
}
MemoryReplayLog is a simple ReplayLog implementation that stores all added sphinx packets and processed batches in memory with no persistence.
This is designed for use just in testing.
func NewMemoryReplayLog ¶
func NewMemoryReplayLog() *MemoryReplayLog
NewMemoryReplayLog constructs a new MemoryReplayLog.
func (*MemoryReplayLog) Delete ¶
func (rl *MemoryReplayLog) Delete(hash *HashPrefix) error
Delete deletes an entry from the log given its hash prefix.
func (*MemoryReplayLog) Get ¶
func (rl *MemoryReplayLog) Get(hash *HashPrefix) (uint32, error)
Get retrieves an entry from the log given its hash prefix. It returns the value stored and an error if one occurs. It returns ErrLogEntryNotFound if the entry is not in the log.
func (*MemoryReplayLog) Put ¶
func (rl *MemoryReplayLog) Put(hash *HashPrefix, cltv uint32) error
Put stores an entry into the log given its hash prefix and an accompanying purposefully general type. It returns ErrReplayedPacket if the provided hash prefix already exists in the log.
func (*MemoryReplayLog) PutBatch ¶
func (rl *MemoryReplayLog) PutBatch(batch *Batch) (*ReplaySet, error)
PutBatch stores a batch of sphinx packets into the log given their hash prefixes and accompanying values. Returns the set of entries in the batch that are replays and an error if one occurs.
func (*MemoryReplayLog) Start ¶
func (rl *MemoryReplayLog) Start() error
Start initializes the log and must be called before any other methods.
func (*MemoryReplayLog) Stop ¶
func (rl *MemoryReplayLog) Stop() error
Stop wipes the state of the log.
type OnionErrorDecrypter ¶
type OnionErrorDecrypter struct {
// contains filtered or unexported fields
}
OnionErrorDecrypter is a struct that's used to decrypt onion errors in response to failed HTLC routing attempts according to BOLT#4.
func NewOnionErrorDecrypter ¶
func NewOnionErrorDecrypter(circuit *Circuit) *OnionErrorDecrypter
NewOnionErrorDecrypter creates new instance of onion decrypter.
func (*OnionErrorDecrypter) DecryptError ¶
DecryptError attempts to decrypt the passed encrypted error response. The onion failure is encrypted in backward manner, starting from the node where error have occurred. As a result, in order to decrypt the error we need get all shared secret and apply decryption in the reverse order.
type OnionErrorEncrypter ¶
type OnionErrorEncrypter struct {
// contains filtered or unexported fields
}
OnionErrorEncrypter is a struct that's used to implement onion error encryption as defined within BOLT0004.
func NewOnionErrorEncrypter ¶
func NewOnionErrorEncrypter(router *Router, ephemeralKey *btcec.PublicKey) (*OnionErrorEncrypter, error)
NewOnionErrorEncrypter creates new instance of the onion encrypter backed by the passed router, with encryption to be doing using the passed ephemeralKey.
func (*OnionErrorEncrypter) Decode ¶
func (o *OnionErrorEncrypter) Decode(r io.Reader) error
Decode restores the encrypter's share secret from the provided io.Reader.
func (*OnionErrorEncrypter) Encode ¶
func (o *OnionErrorEncrypter) Encode(w io.Writer) error
Encode writes the encrypter's shared secret to the provided io.Writer.
func (*OnionErrorEncrypter) EncryptError ¶
func (o *OnionErrorEncrypter) EncryptError(initial bool, data []byte) []byte
EncryptError is used to make data obfuscation using the generated shared secret.
In context of Lightning Network is either used by the nodes in order to make initial obfuscation with the creation of the hmac or by the forwarding nodes for backward failure obfuscation of the onion failure blob. By obfuscating the onion failure on every node in the path we are adding additional step of the security and barrier for malware nodes to retrieve valuable information. The reason for using onion obfuscation is to not give away to the nodes in the payment path the information about the exact failure and its origin.
type OnionPacket ¶
type OnionPacket struct { // Version denotes the version of this onion packet. The version // indicates how a receiver of the packet should interpret the bytes // following this version byte. Currently, a version of 0x00 is the // only defined version type. Version byte // EphemeralKey is the public key that each hop will used in // combination with the private key in an ECDH to derive the shared // secret used to check the HMAC on the packet and also decrypted the // routing information. EphemeralKey *btcec.PublicKey // RoutingInfo is the full routing information for this onion packet. // This encodes all the forwarding instructions for this current hop // and all the hops in the route. RoutingInfo [routingInfoSize]byte // HeaderMAC is an HMAC computed with the shared secret of the routing // data and the associated data for this route. Including the // associated data lets each hop authenticate higher-level data that is // critical for the forwarding of this HTLC. HeaderMAC [hmacSize]byte }
OnionPacket is the onion wrapped hop-to-hop routing information necessary to propagate a message through the mix-net without intermediate nodes having knowledge of their position within the route, the source, the destination, and finally the identities of the past/future nodes in the route. At each hop the ephemeral key is used by the node to perform ECDH between itself and the source node. This derived secret key is used to check the MAC of the entire mix header, decrypt the next set of routing information, and re-randomize the ephemeral key for the next node in the path. This per-hop re-randomization allows us to only propagate a single group element through the onion route.
func NewOnionPacket ¶
func NewOnionPacket(paymentPath []*btcec.PublicKey, sessionKey *btcec.PrivateKey, hopsData []HopData, assocData []byte) (*OnionPacket, error)
NewOnionPacket creates a new onion packet which is capable of obliviously routing a message through the mix-net path outline by 'paymentPath'.
func (*OnionPacket) Decode ¶
func (f *OnionPacket) Decode(r io.Reader) error
Decode fully populates the target ForwardingMessage from the raw bytes encoded within the io.Reader. In the case of any decoding errors, an error will be returned. If the method success, then the new OnionPacket is ready to be processed by an instance of SphinxNode.
type ProcessCode ¶
type ProcessCode int
ProcessCode is an enum-like type which describes to the high-level package user which action should be taken after processing a Sphinx packet.
func (ProcessCode) String ¶
func (p ProcessCode) String() string
String returns a human readable string for each of the ProcessCodes.
type ProcessedPacket ¶
type ProcessedPacket struct { // Action represents the action the caller should take after processing // the packet. Action ProcessCode // ForwardingInstructions is the per-hop payload recovered from the // initial encrypted onion packet. It details how the packet should be // forwarded and also includes information that allows the processor of // the packet to authenticate the information passed within the HTLC. // // NOTE: This field will only be populated iff the above Action is // MoreHops. ForwardingInstructions HopData // NextPacket is the onion packet that should be forwarded to the next // hop as denoted by the ForwardingInstructions field. // // NOTE: This field will only be populated iff the above Action is // MoreHops. NextPacket *OnionPacket }
ProcessedPacket encapsulates the resulting state generated after processing an OnionPacket. A processed packet communicates to the caller what action should be taken after processing.
type ReplayLog ¶
type ReplayLog interface { // Start starts up the log. It returns an error if one occurs. Start() error // Stop safely stops the log. It returns an error if one occurs. Stop() error // Get retrieves an entry from the log given its hash prefix. It returns the // value stored and an error if one occurs. It returns ErrLogEntryNotFound // if the entry is not in the log. Get(*HashPrefix) (uint32, error) // Put stores an entry into the log given its hash prefix and an // accompanying purposefully general type. It returns ErrReplayedPacket if // the provided hash prefix already exists in the log. Put(*HashPrefix, uint32) error // Delete deletes an entry from the log given its hash prefix. Delete(*HashPrefix) error // PutBatch stores a batch of sphinx packets into the log given their hash // prefixes and accompanying values. Returns the set of entries in the batch // that are replays and an error if one occurs. PutBatch(*Batch) (*ReplaySet, error) }
ReplayLog is an interface that defines a log of incoming sphinx packets, enabling strong replay protection. The interface is general to allow implementations near-complete autonomy. All methods must be safe for concurrent access.
type ReplaySet ¶
type ReplaySet struct {
// contains filtered or unexported fields
}
ReplaySet is a data structure used to efficiently record the occurrence of replays, identified by sequence number, when processing a Batch. Its primary functionality includes set construction, membership queries, and merging of replay sets.
func (*ReplaySet) Contains ¶
Contains queries the contents of the replay set for membership of a particular index.
func (*ReplaySet) Decode ¶
Decode reconstructs a replay set given a io.Reader. The byte slice is assumed to be even in length, otherwise resulting in failure.
func (*ReplaySet) Encode ¶
Encode serializes the replay set into an io.Writer suitable for storage. The replay set can be recovered using Decode.
type Router ¶
type Router struct {
// contains filtered or unexported fields
}
Router is an onion router within the Sphinx network. The router is capable of processing incoming Sphinx onion packets thereby "peeling" a layer off the onion encryption which the packet is wrapped with.
func NewRouter ¶
NewRouter creates a new instance of a Sphinx onion Router given the node's currently advertised onion private key, and the target Bitcoin network.
func (*Router) BeginTxn ¶
BeginTxn creates a new transaction that can later be committed back to the sphinx router's replay log.
NOTE: The nels parameter should represent the maximum number of that could be added to the batch, using sequence numbers that match or exceed this value could result in an out-of-bounds panic.
func (*Router) ProcessOnionPacket ¶
func (r *Router) ProcessOnionPacket(onionPkt *OnionPacket, assocData []byte, incomingCltv uint32) (*ProcessedPacket, error)
ProcessOnionPacket processes an incoming onion packet which has been forward to the target Sphinx router. If the encoded ephemeral key isn't on the target Elliptic Curve, then the packet is rejected. Similarly, if the derived shared secret has been seen before the packet is rejected. Finally if the MAC doesn't check the packet is again rejected.
In the case of a successful packet processing, and ProcessedPacket struct is returned which houses the newly parsed packet, along with instructions on what to do next.
func (*Router) ReconstructOnionPacket ¶
func (r *Router) ReconstructOnionPacket(onionPkt *OnionPacket, assocData []byte) (*ProcessedPacket, error)
ReconstructOnionPacket rederives the subsequent onion packet. NOTE: This method does not do any sort of replay protection, and should only be used to reconstruct packets that were successfully processed previously.
type Tx ¶
type Tx struct {
// contains filtered or unexported fields
}
Tx is a transaction consisting of a number of sphinx packets to be atomically written to the replay log. This structure helps to coordinate construction of the underlying Batch object, and to ensure that the result of the processing is idempotent.
func (*Tx) Commit ¶
func (t *Tx) Commit() ([]ProcessedPacket, *ReplaySet, error)
Commit writes this transaction's batch of sphinx packets to the replay log, performing a final check against the log for replays.
func (*Tx) ProcessOnionPacket ¶
func (t *Tx) ProcessOnionPacket(seqNum uint16, onionPkt *OnionPacket, assocData []byte, incomingCltv uint32) error
ProcessOnionPacket processes an incoming onion packet which has been forward to the target Sphinx router. If the encoded ephemeral key isn't on the target Elliptic Curve, then the packet is rejected. Similarly, if the derived shared secret has been seen before the packet is rejected. Finally if the MAC doesn't check the packet is again rejected.
In the case of a successful packet processing, and ProcessedPacket struct is returned which houses the newly parsed packet, along with instructions on what to do next.