github.com/decred/dcrlnd@v0.7.6/watchtower/wtdb/session_info.go (about)

     1  package wtdb
     2  
     3  import (
     4  	"errors"
     5  	"io"
     6  
     7  	"github.com/decred/dcrlnd/watchtower/blob"
     8  	"github.com/decred/dcrlnd/watchtower/wtpolicy"
     9  )
    10  
    11  var (
    12  	// ErrSessionNotFound is returned when querying by session id for a
    13  	// session that does not exist.
    14  	ErrSessionNotFound = errors.New("session not found in db")
    15  
    16  	// ErrSessionAlreadyExists signals that a session creation failed
    17  	// because a session with the same session id already exists.
    18  	ErrSessionAlreadyExists = errors.New("session already exists")
    19  
    20  	// ErrUpdateOutOfOrder is returned when the sequence number is not equal
    21  	// to the server's LastApplied+1.
    22  	ErrUpdateOutOfOrder = errors.New("update sequence number is not " +
    23  		"sequential")
    24  
    25  	// ErrLastAppliedReversion is returned when the client echos a
    26  	// last-applied value that is less than it claimed in a prior update.
    27  	ErrLastAppliedReversion = errors.New("update last applied must be " +
    28  		"non-decreasing")
    29  
    30  	// ErrSeqNumAlreadyApplied is returned when the client sends a sequence
    31  	// number for which they already claim to have an ACK.
    32  	ErrSeqNumAlreadyApplied = errors.New("update sequence number has " +
    33  		"already been applied")
    34  
    35  	// ErrSessionConsumed is returned if the client tries to send a sequence
    36  	// number larger than the session's max number of updates.
    37  	ErrSessionConsumed = errors.New("all session updates have been " +
    38  		"consumed")
    39  )
    40  
    41  // SessionInfo holds the negotiated session parameters for single session id,
    42  // and handles the acceptance and validation of state updates sent by the
    43  // client.
    44  type SessionInfo struct {
    45  	// ID is the remote public key of the watchtower client.
    46  	ID SessionID
    47  
    48  	// Policy holds the negotiated session parameters.
    49  	Policy wtpolicy.Policy
    50  
    51  	// LastApplied the sequence number of the last successful state update.
    52  	LastApplied uint16
    53  
    54  	// ClientLastApplied the last last-applied the client has echoed back.
    55  	ClientLastApplied uint16
    56  
    57  	// RewardAddress the address that the tower's reward will be deposited
    58  	// to if a sweep transaction confirms.
    59  	RewardAddress []byte
    60  
    61  	// TODO(conner): store client metrics, DOS score, etc
    62  }
    63  
    64  // Encode serializes the session info to the given io.Writer.
    65  func (s *SessionInfo) Encode(w io.Writer) error {
    66  	return WriteElements(w,
    67  		s.ID,
    68  		s.Policy,
    69  		s.LastApplied,
    70  		s.ClientLastApplied,
    71  		s.RewardAddress,
    72  	)
    73  }
    74  
    75  // Decode deserializes the session infor from the given io.Reader.
    76  func (s *SessionInfo) Decode(r io.Reader) error {
    77  	return ReadElements(r,
    78  		&s.ID,
    79  		&s.Policy,
    80  		&s.LastApplied,
    81  		&s.ClientLastApplied,
    82  		&s.RewardAddress,
    83  	)
    84  }
    85  
    86  // AcceptUpdateSequence validates that a state update's sequence number and last
    87  // applied are valid given our past history with the client. These checks ensure
    88  // that clients are properly in sync and following the update protocol properly.
    89  // If validation is successful, the receiver's LastApplied and ClientLastApplied
    90  // are updated with the latest values presented by the client. Any errors
    91  // returned from this method are converted into an appropriate
    92  // wtwire.StateUpdateCode.
    93  func (s *SessionInfo) AcceptUpdateSequence(seqNum, lastApplied uint16) error {
    94  	switch {
    95  
    96  	// Client already claims to have an ACK for this seqnum.
    97  	case seqNum <= lastApplied:
    98  		return ErrSeqNumAlreadyApplied
    99  
   100  	// Client echos a last applied that is lower than previously sent.
   101  	case lastApplied < s.ClientLastApplied:
   102  		return ErrLastAppliedReversion
   103  
   104  	// Client update exceeds capacity of session.
   105  	case seqNum > s.Policy.MaxUpdates:
   106  		return ErrSessionConsumed
   107  
   108  	// Client update does not match our expected next seqnum.
   109  	case seqNum != s.LastApplied && seqNum != s.LastApplied+1:
   110  		return ErrUpdateOutOfOrder
   111  	}
   112  
   113  	s.LastApplied = seqNum
   114  	s.ClientLastApplied = lastApplied
   115  
   116  	return nil
   117  }
   118  
   119  // Match is returned in response to a database query for a breach hints
   120  // contained in a particular block. The match encapsulates all data required to
   121  // properly decrypt a client's encrypted blob, and pursue action on behalf of
   122  // the victim by reconstructing the justice transaction and broadcasting it to
   123  // the network.
   124  //
   125  // NOTE: It is possible for a match to cause a false positive, since they are
   126  // matched on a prefix of the txid. In such an event, the likely behavior is
   127  // that the payload will fail to decrypt.
   128  type Match struct {
   129  	// ID is the session id of the client who uploaded the state update.
   130  	ID SessionID
   131  
   132  	// SeqNum is the session sequence number occupied by the client's state
   133  	// update. Together with ID, this allows the tower to derive the
   134  	// appropriate nonce for decryption.
   135  	SeqNum uint16
   136  
   137  	// Hint is the breach hint that triggered the match.
   138  	Hint blob.BreachHint
   139  
   140  	// EncryptedBlob is the encrypted payload containing the justice kit
   141  	// uploaded by the client.
   142  	EncryptedBlob []byte
   143  
   144  	// SessionInfo is the contract negotiated between tower and client, that
   145  	// provides input parameters such as fee rate, reward rate, and reward
   146  	// address when attempting to reconstruct the justice transaction.
   147  	SessionInfo *SessionInfo
   148  }