@@ -10,6 +10,8 @@ import (
10
10
"time"
11
11
12
12
"github.com/btcsuite/btcd/btcec/v2"
13
+ "github.com/btcsuite/btcd/btcec/v2/ecdsa"
14
+ "github.com/btcsuite/btcd/chaincfg/chainhash"
13
15
"github.com/lightninglabs/lightning-node-connect/mailbox"
14
16
"github.com/lightninglabs/lightning-terminal/accounts"
15
17
"github.com/lightninglabs/lightning-terminal/autopilotserver"
@@ -1010,6 +1012,52 @@ func (s *sessionRpcServer) AddAutopilotSession(ctx context.Context,
1010
1012
caveats = append (caveats , firewall .MetaPrivacyCaveat )
1011
1013
}
1012
1014
1015
+ // If a previous session ID has been set to link this new one to, we
1016
+ // first check if we have the referenced session, and we make sure it
1017
+ // has been revoked.
1018
+ var (
1019
+ linkedGroupID * session.ID
1020
+ linkedGroupSession * session.Session
1021
+ )
1022
+ if len (req .LinkedGroupId ) != 0 {
1023
+ var groupID session.ID
1024
+ copy (groupID [:], req .LinkedGroupId )
1025
+
1026
+ // Check that the group actually does exist.
1027
+ groupSess , err := s .cfg .db .GetSessionByID (groupID )
1028
+ if err != nil {
1029
+ return nil , err
1030
+ }
1031
+
1032
+ // Ensure that the linked session is in fact the first session
1033
+ // in its group.
1034
+ if groupSess .ID != groupSess .GroupID {
1035
+ return nil , fmt .Errorf ("can not link to session " +
1036
+ "%x since it is not the first in the session " +
1037
+ "group %x" , groupSess .ID , groupSess .GroupID )
1038
+ }
1039
+
1040
+ // Now we need to check that all the sessions in the group are
1041
+ // no longer active.
1042
+ ok , err := s .cfg .db .CheckSessionGroupPredicate (
1043
+ groupID , func (s * session.Session ) bool {
1044
+ return s .State == session .StateRevoked ||
1045
+ s .State == session .StateExpired
1046
+ },
1047
+ )
1048
+ if err != nil {
1049
+ return nil , err
1050
+ }
1051
+
1052
+ if ! ok {
1053
+ return nil , fmt .Errorf ("a linked session in group " +
1054
+ "%x is still active" , groupID )
1055
+ }
1056
+
1057
+ linkedGroupID = & groupID
1058
+ linkedGroupSession = groupSess
1059
+ }
1060
+
1013
1061
s .sessRegMu .Lock ()
1014
1062
defer s .sessRegMu .Unlock ()
1015
1063
@@ -1021,14 +1069,32 @@ func (s *sessionRpcServer) AddAutopilotSession(ctx context.Context,
1021
1069
sess , err := session .NewSession (
1022
1070
id , localPrivKey , req .Label , session .TypeAutopilot , expiry ,
1023
1071
req .MailboxServerAddr , req .DevServer , perms , caveats ,
1024
- featureConfig , privacy , nil ,
1072
+ featureConfig , privacy , linkedGroupID ,
1025
1073
)
1026
1074
if err != nil {
1027
1075
return nil , fmt .Errorf ("error creating new session: %v" , err )
1028
1076
}
1029
1077
1078
+ // If this session is being linked to a previous one, then we need to
1079
+ // use the previous session's local private key to sign the new
1080
+ // session's public key in order to prove to the Autopilot server that
1081
+ // the two session's belong to the same owner.
1082
+ var (
1083
+ linkSig []byte
1084
+ prevSessionPub * btcec.PublicKey
1085
+ )
1086
+ if linkedGroupID != nil {
1087
+ privKey := linkedGroupSession .LocalPrivateKey
1088
+ pubKey := sess .LocalPublicKey .SerializeCompressed ()
1089
+
1090
+ msg := chainhash .HashB (pubKey )
1091
+ linkSig = ecdsa .Sign (privKey , msg ).Serialize ()
1092
+
1093
+ prevSessionPub = linkedGroupSession .LocalPublicKey
1094
+ }
1095
+
1030
1096
// Register all the privacy map pairs for this session ID.
1031
- privDB := s .cfg .privMap (sess .ID )
1097
+ privDB := s .cfg .privMap (sess .GroupID )
1032
1098
err = privDB .Update (func (tx firewalldb.PrivacyMapTx ) error {
1033
1099
for r , p := range privacyMapPairs {
1034
1100
err := tx .NewPair (r , p )
@@ -1045,7 +1111,7 @@ func (s *sessionRpcServer) AddAutopilotSession(ctx context.Context,
1045
1111
// Attempt to register the session with the Autopilot server.
1046
1112
remoteKey , err := s .cfg .autopilot .RegisterSession (
1047
1113
ctx , sess .LocalPublicKey , sess .ServerAddr , sess .DevServer ,
1048
- featureConfig , nil , nil ,
1114
+ featureConfig , prevSessionPub , linkSig ,
1049
1115
)
1050
1116
if err != nil {
1051
1117
return nil , fmt .Errorf ("error registering session with " +
0 commit comments