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

External staking txs #54

Closed
wants to merge 7 commits into from
Closed

External staking txs #54

wants to merge 7 commits into from

Conversation

maurolacy
Copy link
Collaborator

@maurolacy maurolacy commented Jun 13, 2023

Proof of concept / exploration of transactional remote staking functionality.

Draws from some of the ideas discussed in #49, but does a bare-bones / straightforward impl for clarity. Value ranges are implemented through filtering over transaction types, and a map of pending txs is used for persistence / tracking.

If this is accepted, it can eventually mature and turn into a package or module for implementing the same in other contracts, and supporting other transaction types.

Also, a full impl of this would perhaps require something like two phase commits, as these transactions can involve multiple contracts, and things can fail in any of them.

TODO:

  • Transactional remote unstake.
  • Packaging.
  • Tests.
  • Remote slashing.
  • ...

Copy link
Collaborator

@ethanfrey ethanfrey left a comment

Choose a reason for hiding this comment

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

Okay, my first thought was this was overly complex.
And I saw various errors.

The whole approach is about deeply thinking every code path and ensuring it handles any in-flight transactions using domain knowledge.

This is not safe or scalable. We need to asset a few simple invariants that will detect any potential conflicts and just be responsible to mark where conflicts might occur (much easier than checking every permutation for conflict).

Applying a lock on that user on vault (no deposit, withdraw, or stake) until the pending stake finishes is very safe. And it only provides mild inconvenience to that one user. I would start there, but leave an API that can expand later.

I think something like ValueRange would allow "partial locks" but add a lot more complexity to surrounding computations. Notably, it would be very obvious with it's type, causing exisitng logic to fail to compile, and force updating to handle "ranges of values".

By leaving the same structs and storing something "next to them", which is essential for their validity, it is very easy to overlook it one place and violate constraints. This is the same reason Rust uses Mutex<T> forcing you to take the mutex to touch the type, rather than the C/Java use of a mutex next to an object, which might be forgotten in some code, violating consistency.

Sorry for the long rambling, but this attempt only proved to me why using those locking primitives is the only safe way to start with this. (And we need very clear theoretical arguments why something would always hold if we add a new strategy)

contracts/provider/vault/src/contract.rs Show resolved Hide resolved
.users
.may_load(ctx.deps.storage, &ctx.info.sender)?
.unwrap_or_default();
user.max_lien = user.max_lien.max(lien.amount);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Even if lein was properly updated, this doesn't handle multiple in-flight tx on the same lienholder.

eg. I have 40 collateral. I had a lien of 20 on X (only one, my max)

A. Try to stake 10 to X -> max(20, 20 + 10) = 30 .... this passes check, but not persisted.
B. Try to stake 20 to X -> max(20, 20 + 20) = 40 ... this passes check but not persisted.

If both get success acks, then we have 20 + 10 + 20 = 50 bonded.

Copy link
Collaborator Author

@maurolacy maurolacy Jun 13, 2023

Choose a reason for hiding this comment

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

Again, you're right. This would require to look for the max of the liens over the sum of the pending ones. Will fix for referenceFixed?

I agree this is overly complex to be able to reason about it clearly, or in a simple way. But, I'm still not convinced the "value ranges" / "partial locking" approach will make our lives simpler.


let amount = amount.amount;
// Tx starts here
// Verify that the user has enough collateral to stake this and the currently pending txs
Copy link
Collaborator

Choose a reason for hiding this comment

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

This looks correct, but way too complex not to assume someone will miss a case.

@maurolacy maurolacy mentioned this pull request Jun 15, 2023
8 tasks
@ethanfrey
Copy link
Collaborator

This is replaced by #57 so do you want to close it? (I'm try to clean up... there were too many open PRs)

@maurolacy
Copy link
Collaborator Author

Closing in favour of #57.

@maurolacy maurolacy closed this Jun 17, 2023
@maurolacy maurolacy deleted the external-staking-txs branch November 6, 2023 08:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants