-
Notifications
You must be signed in to change notification settings - Fork 116
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[7/?] StaticAddr: Loop-In #786
base: static-addr-staging
Are you sure you want to change the base?
Conversation
d807a95
to
e635d63
Compare
d813b20
to
447d70d
Compare
7ee61f6
to
3eb5bd2
Compare
e635d63
to
2c94110
Compare
a151ffd
to
d69e9d5
Compare
2c94110
to
ae3a983
Compare
ae3a983
to
0e92035
Compare
127d76c
to
a9d9e6f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed only the first commit with protobuf types "looprpc: static address loop-ins".
|
||
/* | ||
EXPIRED indicates that the deposit has expired and the sweep transaction | ||
has been sufficiently confirmed. | ||
*/ | ||
EXPIRED = 6; | ||
EXPIRED = 10; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe rename this state to EXPIRY_SWEEP_CONFIRMED
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These states were introduced in a different PR, so I'd add create a separate refactor PR to fix these up.
// Examples: | ||
// loopd/v0.10.0-beta/commit=3b635821 | ||
// litd/v0.2.0-alpha/commit=326d754 | ||
string user_agent = 7; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is StaticAddressLoopInRequest.initiator
appended to this field? Can you provide an example of such a user agent in the description, denoting where is the initiator
part, please?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again thanks for poking, I was using the initator as the user agent, but there's actually a function that appends the right info so that it matches the examples. Have a look at https://github.com/lightninglabs/loop/blob/master/version.go#L57. Will update the PR
swapserverrpc/server.proto
Outdated
// The address that the server wants to sweep the static address deposits | ||
// to. | ||
string sweepless_sweep_addr = 3; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we replace an address with an unsigned tx to provide more flexibility?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With flexibility you mean that if the sweepless sweep tx has different parameters in the future we wouldn't have to modify these rpc messages, but the client would just blindly sign any tx?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that is the idea. Then we can implement sweep batching without asking clients to update.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed another 3 commits:
- sqlc: loop-in tables and queries
- log: static address loop-in logging
- staticaddr: deposit changes to be squashed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome and huge work! 🥇 Did the first detailed pass, going to spend some more time with testing and reading through the whole code again now 🧪
staticaddr/loopin/manager.go
Outdated
// Check that the label is valid. | ||
err := labels.Validate(req.Label) | ||
if err != nil { | ||
return fmt.Errorf("invalid label: %v", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: %w here and everywhere else where we decorate errors.
staticaddr/loopin/manager.go
Outdated
// InitiateLoopIn initiates a loop-in swap. It passes the request to the server | ||
// along with all relevant loop-in information. | ||
func (m *Manager) InitiateLoopIn(req *loop.StaticAddressLoopInRequest) error { | ||
loopIn := &StaticAddressLoopIn{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we could reorder the code a bit so that validation of all fields that needs to be validated is followed by the swap creation/init etc.
deposit_outpoints BLOB NOT NULL, | ||
|
||
-- htlc_tx contains the htlc transaction without signatures. | ||
htlc_tx BLOB, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think storing the htlc is only minimally convenient vs regenerating it at runtime. I'd consider not storing it as a better alternative.
htlc_tx_fee_rate BIGINT NOT NULL, | ||
|
||
-- htlc_timeout_sweep_tx_hash contains the htlc timeout sweep tx hash. | ||
htlc_timeout_sweep_tx_hash BLOB, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I propose to store the string converted tx id instead as it is easier to use if queried manually.
|
||
-- deposit_outpoints is a concatenated list of outpoints that are used for | ||
-- this swap. The list has the format txid1:idx;txid2:idx;... | ||
deposit_outpoints BLOB NOT NULL, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps consider human readable storage so it is easier to use if queried manually.
staticaddr/loopin/actions.go
Outdated
err = f.cfg.WalletKit.PublishTransaction(f.ctx, timeoutTx, txLabel) | ||
if err != nil { | ||
if !strings.Contains(err.Error(), "output already spent") { | ||
log.Errorf("%v: %v", txLabel, err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: f.Errorf
, and some more context could be useful.
|
||
// Retrieve all deposits referenced by the outpoints and ensure that | ||
// they are in state Deposited. | ||
deposits, active := m.cfg.DepositManager.AllStringOutpointsActiveDeposits( //nolint:lll |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
staticaddr/loopin/actions.go
Outdated
@@ -118,21 +118,53 @@ func (f *FSM) InitHtlcAction(_ fsm.EventContext) fsm.EventType { | |||
} | |||
|
|||
f.loopIn.HtlcCltvExpiry = loopInResp.HtlcExpiry | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: could you pls add more detail to the commit message?
staticaddr/loopin/actions.go
Outdated
fee := f.loopIn.HtlcTxFeeRate.FeeForWeight(f.loopIn.htlcWeight()) | ||
feeRate := chainfee.SatPerKWeight(loopInResp.HtlcFeeRate) | ||
fee := feeRate.FeeForWeight(f.loopIn.htlcWeight()) | ||
if fee > f.loopIn.TotalDepositAmount()/5 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: instead of writing TotalDepositAmount()/5
everywhere, please add a variable tracking this value.
ce7be09
to
6cee2fe
Compare
bd416b7
to
04f8541
Compare
Thanks @bhandras for your review and the nice suggestions. I've addressed your comments. |
d394459
to
2fe6195
Compare
swapserverrpc/server.proto
Outdated
repeated bytes sweepless_client_sigs = 3; | ||
} | ||
|
||
message PushStaticAddressSweeplessSigsResponse { | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add line end
cmd/loop/main.go
Outdated
@@ -280,6 +280,12 @@ func displayInDetails(req *looprpc.QuoteRequest, | |||
"wallet.\n\n") | |||
} | |||
|
|||
if req.DepositOutpoints != nil { | |||
fmt.Printf("On-chain fees for static address loop-ins is not " + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/is not/are not/
cmd/loop/staticaddr.go
Outdated
@@ -229,9 +257,21 @@ func summary(ctx *cli.Context) error { | |||
case "withdrawn": | |||
filterState = looprpc.DepositState_WITHDRAWN | |||
|
|||
case "loopingin": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/loopingin/looping_in/
s/loopedin/looped_in/
here and in the help message.
for _, outpoint := range outpoints { | ||
if deposit, ok := depositMap[outpoint]; ok { | ||
sum += deposit.Value | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we do something if the outpoint is not in depositMap
? Log or return an error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added an error and fail the loop-in attempt if that scenario hits.
cmd/loop/staticaddr.go
Outdated
return nil | ||
} | ||
|
||
func sumDeposits(outpoints []string, deposits []*looprpc.Deposit) int64 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if an outpoint or a deposit is non-unique? Should we check this and return an error if this is detected?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added containsDuplicates
after the outpoint selection is done.
ClientKeyIndex: int32(loopIn.HtlcKeyLocator.Index), | ||
} | ||
|
||
joinedOutpoints := strings.Join( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check that elements of loopIn.DepositOutpoints
do not contain outpointSeparator
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡
} | ||
|
||
// toStaticAddressLoopIn converts sql rows to an instant out struct. | ||
func toStaticAddressLoopIn(_ context.Context, network *chaincfg.Params, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add unit test.
staticaddr/withdraw/manager.go
Outdated
@@ -430,20 +408,19 @@ func (m *Manager) handleWithdrawal(deposits []*deposit.Deposit, | |||
deposit.Withdrawn, | |||
) | |||
if err != nil { | |||
log.Errorf("Error transitioning deposits: %v", | |||
log.Errorf("Error transitioning deposits: %w", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
%w should not be used in log. It will be logged as a wrong format.
I found more instances of this issue:
loop$ git grep -w log | grep %w
staticaddr/deposit/actions.go: log.Errorf("%v: %w", txLabel, err)
staticaddr/deposit/actions.go: log.Debugf("error while sweeping expired deposit: %w", err)
staticaddr/deposit/manager.go: log.Errorf("Error sending OnStart event: %w",
staticaddr/deposit/manager.go: log.Errorf("Error sending OnStart event: %w", err)
staticaddr/loopin/actions.go: log.Warnf("unable to decode sweep address: %w", err)
staticaddr/loopin/actions.go: log.Errorf("%v: %w", txLabel, err)
staticaddr/loopin/fsm.go: log.Errorf("Error checking if loop-in is stored: %w", err)
staticaddr/loopin/fsm.go: log.Errorf("Error updating loop-in: %w", err)
staticaddr/loopin/manager.go: log.Errorf("Error sending OnStart event: %w",
staticaddr/loopin/manager.go: log.Errorf("Error sending OnNewRequest event: %w", err)
staticaddr/withdraw/manager.go: log.Errorf("Error republishing withdrawals: %w",
staticaddr/withdraw/manager.go: log.Errorf("%v: %w", txLabel, err)
staticaddr/withdraw/manager.go: log.Errorf("Error transitioning deposits: %w",
staticaddr/withdraw/manager.go: log.Errorf("Error waiting for confirmation: %w", err)
staticaddr/withdraw/manager.go: log.Errorf("Error republishing withdrawal: %w", err)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for the hints, fixed.
swapserverrpc/server.proto
Outdated
bytes swap_hash = 1; | ||
|
||
// The nonces that the client used to generate the htlc sigs. | ||
repeated bytes htlc_client_nonces = 2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I propose to make a sub-message including two fields: htlc_client_nonces and sigs. Then we can use it 3 times for normal, high and extremely high fee levels.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
swapserverrpc/server.proto
Outdated
int32 htlc_expiry = 2; | ||
|
||
// The nonces that the server used to generate the partial htlc tx sigs. | ||
repeated bytes htlc_server_nonces = 3; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I propose to group the fields: make a sub-message including two fields: htlc_server_nonces and fee_rate. Then we can use it 3 times here for normal, high and extremely high fee levels.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
very good suggestion, thanks
2fe6195
to
93db4df
Compare
Doing some manual testing now, gonna add some notes here and update them:
|
93db4df
to
c8c1462
Compare
96c7526
to
c6e7a43
Compare
These deposit changes will be squashed into the original commits once merged into staging.
c6e7a43
to
2a89748
Compare
This PR introduces loop-ins of static address deposits.
The client/server interaction is depicted below:
Open tasks that need resolution until this PR can leave draft mode:
Previously merged PRs:
#642
#650
#677
#719
#721
#750
master...static-addr-staging