Skip to content
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

Fixes locking issues when creating channel / adding funds #2640

Merged
merged 10 commits into from
Aug 6, 2020

Conversation

dirkmc
Copy link
Contributor

@dirkmc dirkmc commented Jul 28, 2020

Currently when creating a channel or adding funds to an existing channel, the payment channel manager locks up until the messages have been confirmed on chain, which can take several minutes.

This PR resolves the locking issue:

  • Operations on each channel are executed sequentially
  • Operations on different channels can run in parallel

This PR also manages the state of requests and restores them if lotus is shut down and restarted:

  • On startup checks for pending create channel / add funds messages that have been sent to chain
  • Writes state to the datastore each time there's a state change
  • Keeps track of channels by from / to instead of by channel address, so that state can be written even before channel has been created

This PR also

  • sets a flag on channels that are in the "settling" state
  • creates a new channel if there is a subsequent call to add funds to that From and To

@dirkmc dirkmc changed the base branch from master to next July 28, 2020 23:24
@dirkmc dirkmc force-pushed the fix/store-locking branch 2 times, most recently from a2c541e to 4a6362b Compare July 29, 2020 17:57
@dirkmc dirkmc force-pushed the fix/store-locking branch 2 times, most recently from 1e86e83 to b41ace0 Compare August 4, 2020 16:22
api/apistruct/struct.go Outdated Show resolved Hide resolved
@@ -274,6 +275,7 @@ func Online() Option {

Override(new(*paychmgr.Store), paychmgr.NewStore),
Override(new(*paychmgr.Manager), paychmgr.NewManager),
Override(HandlePaymentChannelManagerKey, paychmgr.HandleManager),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On startup we need to restart tracking of payment channel add funds requests that have already been sent to chain

node/impl/paych/paych.go Show resolved Hide resolved
paychmgr/manager.go Outdated Show resolved Hide resolved
}

func (pm *Manager) OutboundChanTo(from, to address.Address) (address.Address, error) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OutboundChanTo() wasn't being used anywhere so I removed it


// laneState gets the LaneStates from chain, then applies all vouchers in
// the data store over the chain state
func (ca *channelAccessor) laneState(state *paych.State, ch address.Address) (map[uint64]*paych.LaneState, error) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

laneState() and totalRedeemedWithVoucher() were just moved from state.go


// laneState gets the LaneStates from chain, then applies all vouchers in
// the data store over the chain state
func (pm *Manager) laneState(state *paych.State, ch address.Address) (map[uint64]*paych.LaneState, error) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

laneState() and totalRedeemedWithVoucher() were just moved to paych.go

@dirkmc dirkmc marked this pull request as ready for review August 4, 2020 23:06
paychmgr/manager.go Outdated Show resolved Hide resolved
Copy link
Contributor

@magik6k magik6k left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is so much better!

Generally looks good, just a couple of comments.

Running go test -count 100 ./paychmgr seems to produce some test failures on my PC -> https://gist.github.com/magik6k/2b09f76c40418a0c7553fc14ded0ae2f

Comment on lines -55 to -56
// TODO: wait outside the store lock!
// (tricky because we need to setup channel tracking before we know its address)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

api/apistruct/struct.go Outdated Show resolved Hide resolved
@dirkmc
Copy link
Contributor Author

dirkmc commented Aug 5, 2020

@magik6k I was able to repro the issues you were seeing when you ran 100 tests. There was a sync issue in the mocks for mempool / state wait that I believe was causing the issues, I've fixed it now and it works for me.
Separately I noticed a couple of missing locks so I added those as well.

Note that it's ok for the tests to output error logs - some of the tests are designed to trigger error cases and then test that the paych manager handles errors correctly.

Please take another look and let me know if it works for you now.

@dirkmc dirkmc requested a review from magik6k August 5, 2020 22:03
Copy link
Member

@whyrusleeping whyrusleeping left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple comments, but overall this looks really good, excited to have this in soon!

Copy link
Contributor

@hannahhoward hannahhoward left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wrote a lot of suggestions and ideas, but generally these are improvements / future tickets rather than blocking issues.

However, the one thing I need to at minimum confirm is your intention (and if so, understand why) is keying the channels on -from->to- -- it seems like we should be using the UUID, cause otherwise we're overwriting channels potentially. I guess if they're not active that's ok, maybe even preferable, but it still feels odd to have the uuid if we're not really using it that much (I guess we're using it for messages)

node/impl/paych/paych.go Show resolved Hide resolved
paychmgr/manager.go Show resolved Hide resolved
}

func (ps *Store) VouchersForPaych(ch address.Address) ([]*VoucherInfo, error) {
ci, err := ps.getChannelInfo(ch)
// TODO: This is a hack to get around not being able to CBOR marshall a nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eeek how annoying!

paychmgr/store.go Outdated Show resolved Hide resolved
}

// Change the state of the channel in the store
func (ca *channelAccessor) mutateChannelInfo(from address.Address, to address.Address, mutate func(*ChannelInfo)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it may be worth looking at go-statestore even if you're not using go-statemachine cause it provides some of this functionality in a simple form. (for the future)

paychmgr/msglistener.go Show resolved Hide resolved
if err != nil {
return types.NewInt(0), err
return types.BigInt{}, err
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does Lotus still have a BigInt type of its own? I feel like at this point all our money types should come from spec-actors abi package? Future refactor.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's an alias of the spec type, we just never got around to getting rid of it

node/impl/paych/paych.go Show resolved Hide resolved
paychmgr/settle_test.go Show resolved Hide resolved
paychmgr/simple.go Show resolved Hide resolved
paychmgr/manager.go Outdated Show resolved Hide resolved
Copy link
Contributor

@hannahhoward hannahhoward left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM all other comments non-blocking

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/payment-channel Area: Payment Channel
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants