-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #690 from near/xiangyi/replace_panic_str_w_err
contract: return error rather than panic whenever possible
- Loading branch information
Showing
13 changed files
with
452 additions
and
238 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# Chain Signatures API | ||
|
||
## `sign()` | ||
This is the main function of the contract API. It is used to sign a request with the MPC service. | ||
```rust | ||
pub fn sign(&mut self, request: SignRequest) -> Result<near_sdk::Promise, MpcContractError> | ||
``` | ||
Arguments and return type: | ||
```rust | ||
pub struct SignRequest { | ||
pub payload: [u8; 32], | ||
pub path: String, | ||
pub key_version: u32, | ||
} | ||
|
||
pub struct SignResult { | ||
pub big_r: String, | ||
pub s: String, | ||
} | ||
``` | ||
- `key_version` must be less than or equal to the value at `latest_key_version`. | ||
- `path` is a derivation path for the key that will be used to sign the payload. | ||
- To avoid overloading the network with too many requests, we ask for a small deposit for each signature request. The fee changes based on how busy the network is. | ||
|
||
## `public_key()` | ||
This is the root public key combined from all the public keys of the participants. | ||
```rust | ||
pub fn public_key(&self) -> Result<PublicKey, MpcContractError> | ||
``` | ||
|
||
## `derived_public_key()` | ||
This is the derived public key of the caller given path and predecessor. If the predecessor is not provided, it will be the caller of the contract. | ||
```rust | ||
pub fn derived_public_key( | ||
&self, | ||
path: String, | ||
predecessor: Option<AccountId>, | ||
) -> Result<PublicKey, MpcContractError> | ||
``` | ||
|
||
## `latest_key_version()` | ||
Key versions refer new versions of the root key that we may choose to generate on cohort changes. Older key versions will always work but newer key versions were never held by older signers. Newer key versions may also add new security features, like only existing within a secure enclave. Currently only 0 is a valid key version. | ||
```rust | ||
pub const fn latest_key_version(&self) -> u32 | ||
``` | ||
|
||
For more details check `User contract API` impl block in the [chain-signatures/contracts/src/lib.rs](./chain-signatures/contracts/src/lib.rs) file. | ||
|
||
# Environments | ||
Currently, we have 3 environments: | ||
1. Mainnet: `v1.multichain-mpc.near` // TODO: set when available | ||
2. Testnet: `v2.multichain-mpc.testnet` | ||
3. Dev: `v5.multichain-mpc-dev.testnet` | ||
|
||
Contracts can be changed from v1 to v2, etc. Older contracts should continue functioning. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
use near_sdk::Gas; | ||
|
||
#[derive(Debug, thiserror::Error)] | ||
pub enum SignError { | ||
#[error("Signature request has timed out.")] | ||
Timeout, | ||
#[error("Signature request has already been submitted. Please try again later.")] | ||
PayloadCollision, | ||
#[error("Malformed payload: {0}")] | ||
MalformedPayload(String), | ||
#[error( | ||
"This key version is not supported. Call latest_key_version() to get the latest supported version." | ||
)] | ||
UnsupportedKeyVersion, | ||
#[error("Attached deposit is lower than required. Attached: {0}, Required: {1}.")] | ||
InsufficientDeposit(u128, u128), | ||
#[error("Provided gas is lower than required. Provided: {0}, required {1}.")] | ||
InsufficientGas(Gas, Gas), | ||
#[error("Too many pending requests. Please try again later.")] | ||
RequestLimitExceeded, | ||
#[error("This sign request has timed out, was completed, or never existed.")] | ||
RequestNotFound, | ||
} | ||
|
||
#[derive(Debug, thiserror::Error)] | ||
pub enum RespondError { | ||
#[error("This sign request has timed out, was completed, or never existed.")] | ||
RequestNotFound, | ||
#[error("The provided signature is invalid.")] | ||
InvalidSignature, | ||
#[error("The protocol is not Running.")] | ||
ProtocolNotInRunningState, | ||
} | ||
|
||
#[derive(Debug, thiserror::Error)] | ||
pub enum JoinError { | ||
#[error("The protocol is not Running.")] | ||
ProtocolStateNotRunning, | ||
} | ||
|
||
#[derive(Debug, thiserror::Error)] | ||
pub enum PublicKeyError { | ||
#[error("Protocol state is not running or resharing.")] | ||
ProtocolStateNotRunningOrResharing, | ||
#[error("Derived key conversion failed.")] | ||
DerivedKeyConversionFailed, | ||
} | ||
|
||
#[derive(Debug, thiserror::Error)] | ||
pub enum InitError { | ||
#[error("Threshold cannot be greater than the number of candidates")] | ||
ThresholdTooHigh, | ||
} | ||
|
||
#[derive(Debug, thiserror::Error)] | ||
pub enum VoteError { | ||
#[error("Voting account is not in the participant set.")] | ||
VoterNotParticipant, | ||
#[error("Account to be kicked is not in the participant set.")] | ||
KickNotParticipant, | ||
#[error("Account to join is not in the candidate set.")] | ||
JoinNotCandidate, | ||
#[error("Account to join is already in the participant set.")] | ||
JoinAlreadyParticipant, | ||
#[error("Mismatched epoch.")] | ||
EpochMismatch, | ||
#[error("Number of participants cannot go below threshold.")] | ||
ParticipantsBelowThreshold, | ||
#[error("Unexpected protocol state: {0}")] | ||
UnexpectedProtocolState(String), | ||
} | ||
|
||
#[derive(Debug, thiserror::Error)] | ||
pub enum MpcContractError { | ||
#[error("sign fn error: {0}")] | ||
SignError(SignError), | ||
#[error("respond fn error: {0}")] | ||
RespondError(RespondError), | ||
#[error("vote_* fn error: {0}")] | ||
VoteError(VoteError), | ||
#[error("init fn error: {0}")] | ||
InitError(InitError), | ||
#[error("join fn error: {0}")] | ||
JoinError(JoinError), | ||
#[error("public_key fn error: {0}")] | ||
PublicKeyError(PublicKeyError), | ||
} | ||
|
||
impl near_sdk::FunctionError for MpcContractError { | ||
fn panic(&self) -> ! { | ||
crate::env::panic_str(&self.to_string()) | ||
} | ||
} |
Oops, something went wrong.