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 }