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

Support staking on Harmony from ONE Wallet #9

Closed
polymorpher opened this issue Jun 27, 2021 · 7 comments
Closed

Support staking on Harmony from ONE Wallet #9

polymorpher opened this issue Jun 27, 2021 · 7 comments
Assignees

Comments

@polymorpher
Copy link
Owner

polymorpher commented Jun 27, 2021

The main difference between staking from a smart contract wallet (like this one) and staking from an externally owned account is that a smart contract wallet does not have a key to sign the staking transaction. Thus, special procedures must be created to reconcile this difference if we are to support staking from ONE wallet.

To give the reader some background context, let us first examine the status quo procedure to validate a staking request from a private-key based wallet (i.e. externally owned account, or EOA). This is documented briefly in Harmony documentation. Here is a more elaborated description:

  1. first, the EOA wallet signs a staking transaction and sends an RPC request under hmy_sendrawstakingtransaction carrying a StakingTransaction.
  2. The node receiving the RPC request would invoke the RPC's handler, which performs a series of operations and eventually validates the transaction before adding it to a transaction pool
  3. During the validation in (2), the sender's signature is verified using the standard ECDSA algorithm based on the signature (r, s, v values) provided by the EOA wallet within the transaction. See 1, 2, 3, 4, and eventually 5.

Since smart contract wallets cannot keep the private key for ECDSA, it generally cannot produce ECDSA signatures unless the signing is deferred to a client which has the private key and would request approval from the user to sign. Nonetheless, the signature produced by the client would be a signature for the client's EOA wallet's address, which is not valid for the smart contract wallet's address. However, a more fundamental issue is that ONE Wallet does not have private key at the client side at all, nor uses private key anywhere (aside from being part of the composable authentication scheme in the future, which is not yet implemented and should be considered as an advanced security feature). Therefore, it is not possible to use the same procedure under RPC hmy_sendrawstakingtransaction to implement staking from ONE Wallet.

I see two three approaches to solve to this problem.

  1. Create a standard staking smart contract and a pool service protocol. Based on the contract and the protocol, establish multiple staking pools that offers staking as an on-chain service. Each staking pool would manage its own EOA wallets that aggregates the staked ONEs, and perform the actual using pre-existing RPC call (hmy_sendrawstakingtransaction) and the status quo procedure. Obviously, this approach relies on the honesty and security of the pools. If a pool is hacked, or becomes malicious and runs away with the staked ONEs, all users who staked their funds to that pool would lose their funds.

  2. Modify the EVM code and add a special function to the smart contract that allows staking as a native function call. The signature validation should be performed by calling isValidSignature function on the contract, per EIP-1271 . This approach is much more secure, but the implementation can be complex. I am not familiar with that part of the code so at this time I only know it would not be as simple as adding a precompiled contract, since this native function would call non-native function to validate the signature, and would have side effects (changing balance of the contract). This approach also requires all validators to upgrade to a new version of Harmony node once the implementation is done.

  3. See the comment below Support staking on Harmony from ONE Wallet #9 (comment)

@lijiang2087
Copy link

💪1️⃣💎

@polymorpher
Copy link
Owner Author

polymorpher commented Jun 27, 2021

A third alternative is to alter 1 and validate signature differently, if the sender of the transaction is a contract. Since StakingTransaction relies on (r, s, v) signature values to calculate the sender's address, we should be extend StakingTransaction to accept a new type of StakingMsg and to include the contract's address, as well as the proof needed for validation. The validation of proof can be a call to a function on the contract (isValidSignature per EIP-1271), or hard-coded in Go similar to the flow in https://github.com/polymorpher/one-wallet/blob/master/code/contracts/ONEWallet.sol#L171.

At runtime, the client submits the staking request directly via hmy_sendrawstakingtransaction RPC call using the altered StakingTransaction structure proposed above.

This alternative requires much less modification compared to (2). It does not venture into customizing EVM and only customizes components that are already customized (RPC servers).

@rlan35
Copy link

rlan35 commented Jun 28, 2021

A third alternative is to alter 1 and validate signature differently, if the sender of the transaction is a contract. Since StakingTransaction relies on (r, s, v) signature values to calculate the sender's address, we should be extend StakingTransaction to accept a new type of StakingMsg and to include the contract's address, as well as the proof needed for validation. The validation of proof can be a call to a function on the contract (isValidSignature per EIP-1271), or hard-coded in Go similar to the flow in https://github.com/polymorpher/one-wallet/blob/master/code/contracts/ONEWallet.sol#L171.

At runtime, the client submits the staking request directly via hmy_sendrawstakingtransaction RPC call using the altered StakingTransaction structure proposed above.

This alternative requires much less modification compared to (2). It does not venture into customizing EVM and only customizes components that are already customized (RPC servers).

The 3rd option is a viable option but it seems to me very hacky. It's altering staking txn structure and also staking txn validation logic, which is as heavy-weight as option 2 I think (the difference is it's not touching evm). Actually I think the option 2 is more elegant and generic and will help all other smart contract staking operations. I would prefer to go with option 2 even though it may take more time to implement.

Btw, we are making good progress on account abstraction: harmony-one/bounties#35. Though I don't think it will save us from having to change the staking logic on our side.

@hashmesan
Copy link

Btw, we are making good progress on account abstraction: harmony-one/bounties#35. Though I don't think it will save us from having to change the staking logic on our side.

@rlan35 When do you think it will be ready on testnet or mainnet?

@polymorpher
Copy link
Owner Author

Gnosis Safe is sort of handling contract signatures via options 3, by accepting the case that v=0 and using a variable length signature. See https://github.com/gnosis/safe-contracts/blob/34c87b783dfd04ff09ef7c358c3182c3c151e086/contracts/GnosisSafe.sol#L257

@polymorpher
Copy link
Owner Author

polymorpher commented Mar 4, 2022

As of today, delegate and undelegate are added as smart contract functions (pre-compiled) on Harmony. Staking support on 1wallet is set to be added in mid March. harmony-one/harmony#3906

@polymorpher
Copy link
Owner Author

Fixed by #268

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

No branches or pull requests

4 participants