@@ -169,6 +169,11 @@ func (m *Manager) Run(ctx context.Context, bestBlock uint32) error {
169169 return err
170170 }
171171
172+ // Wake the manager up very 10 seconds to check if there're any pending
173+ // chores to do.
174+ const wakeupInterval = time .Duration (10 ) * time .Second
175+ withdrawTicker := time .NewTicker (wakeupInterval )
176+
172177 for {
173178 select {
174179 case <- m .callEnter :
@@ -188,6 +193,15 @@ func (m *Manager) Run(ctx context.Context, bestBlock uint32) error {
188193 return err
189194 }
190195
196+ case <- withdrawTicker .C :
197+ err := m .publishPendingWithdrawals (ctx )
198+ if err != nil {
199+ log .Errorf ("Unable to publish pending " +
200+ "withdrawals: %v" , err )
201+
202+ return err
203+ }
204+
191205 case err := <- blockErrChan :
192206 log .Errorf ("received error from block epoch " +
193207 "notification: %v" , err )
@@ -944,6 +958,8 @@ func (m *Manager) handleDepositSpend(ctx context.Context, d *Deposit,
944958
945959 switch d .State {
946960 case StateTimeoutSweepPublished :
961+ fallthrough
962+ case StateCooperativeSweepPublished :
947963 d .State = StateSwept
948964
949965 err := m .releaseDepositSweepInputs (ctx , d )
@@ -1085,3 +1101,73 @@ func (m *Manager) WithdrawDeposits(ctx context.Context,
10851101
10861102 return nil
10871103}
1104+
1105+ // publishPendingWithdrawals publishes any pending deposit withdrawals.
1106+ func (m * Manager ) publishPendingWithdrawals (ctx context.Context ) error {
1107+ for _ , d := range m .deposits {
1108+ // TODO(bhandras): republish on StateCooperativeSweepPublished.
1109+ if d .State != StateWithdrawn {
1110+ continue
1111+ }
1112+
1113+ serverKey , err := m .store .GetAssetDepositServerKey (
1114+ ctx , d .ID ,
1115+ )
1116+ if err != nil {
1117+ return err
1118+ }
1119+
1120+ lockID , err := d .lockID ()
1121+ if err != nil {
1122+ return err
1123+ }
1124+
1125+ // TODO(bhandras): conf target should be dynamic/configrable.
1126+ const confTarget = 2
1127+ feeRateSatPerKw , err := m .walletKit .EstimateFeeRate (
1128+ ctx , confTarget ,
1129+ )
1130+ if err != nil {
1131+ return err
1132+ }
1133+
1134+ funder := true
1135+ sendResp , err := m .sweeper .PublishDepositSweepMuSig2 (
1136+ ctx , d .Kit , funder , d .Proof , serverKey ,
1137+ asset .NewScriptKey (d .SweepScriptKey ),
1138+ d .SweepInternalKey , d .withdrawLabel (),
1139+ feeRateSatPerKw .FeePerVByte (), lockID , lockExpiration ,
1140+ )
1141+ if err != nil {
1142+ log .Errorf ("Unable to publish deposit sweep for %v: %v" ,
1143+ d .ID , err )
1144+ } else {
1145+ log .Infof ("Published sweep for deposit %v: %v" , d .ID ,
1146+ sendResp .Transfer .AnchorTxHash )
1147+
1148+ d .State = StateCooperativeSweepPublished
1149+ err = m .handleDepositStateUpdate (ctx , d )
1150+ if err != nil {
1151+ log .Errorf ("Unable to update deposit %v " +
1152+ "state: %v" , d .ID , err )
1153+
1154+ return err
1155+ }
1156+ }
1157+
1158+ // Start monitoring the sweep unless we're already doing so.
1159+ if _ , ok := m .pendingSweeps [d .ID ]; ! ok {
1160+ err := m .waitForDepositSweep (ctx , d , d .withdrawLabel ())
1161+ if err != nil {
1162+ log .Errorf ("Unable to wait for deposit %v " +
1163+ "spend: %v" , d .ID , err )
1164+
1165+ return err
1166+ }
1167+
1168+ m .pendingSweeps [d .ID ] = struct {}{}
1169+ }
1170+ }
1171+
1172+ return nil
1173+ }
0 commit comments