mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 12:19:24 +00:00
Add validator sets RPC functions necessary for the coordinator
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
use core::str::FromStr;
|
||||||
|
|
||||||
use borsh::BorshDeserialize;
|
use borsh::BorshDeserialize;
|
||||||
|
|
||||||
pub use serai_abi::{
|
pub use serai_abi::{
|
||||||
@@ -145,6 +147,72 @@ impl<'serai> ValidatorSets<'serai> {
|
|||||||
.map_err(|_| RpcError::InvalidNode("validator set's keys weren't a valid key pair".to_string()))
|
.map_err(|_| RpcError::InvalidNode("validator set's keys weren't a valid key pair".to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The current validators for the specified network.
|
||||||
|
pub async fn current_validators(
|
||||||
|
&self,
|
||||||
|
network: NetworkId,
|
||||||
|
) -> Result<Option<Vec<SeraiAddress>>, RpcError> {
|
||||||
|
self
|
||||||
|
.0
|
||||||
|
.call::<Option<Vec<String>>>(
|
||||||
|
"validator-sets/current_validators",
|
||||||
|
&format!(r#", "network": {} "#, rpc_network(network)?),
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
.map(|validators| {
|
||||||
|
validators
|
||||||
|
.into_iter()
|
||||||
|
.map(|addr| {
|
||||||
|
SeraiAddress::from_str(&addr)
|
||||||
|
.map_err(|_| RpcError::InvalidNode("validator's address was invalid".to_string()))
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
})
|
||||||
|
.transpose()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If the prior validators for this network is still expected to publish a slash report.
|
||||||
|
pub async fn pending_slash_report(&self, network: ExternalNetworkId) -> Result<bool, RpcError> {
|
||||||
|
self
|
||||||
|
.0
|
||||||
|
.call(
|
||||||
|
"validator-sets/pending_slash_report",
|
||||||
|
&format!(r#", "network": {} "#, rpc_network(network)?),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The key on an embedded elliptic curve for the specified validator.
|
||||||
|
pub async fn embedded_elliptic_curve_keys(
|
||||||
|
&self,
|
||||||
|
validator: SeraiAddress,
|
||||||
|
network: ExternalNetworkId,
|
||||||
|
) -> Result<Option<EmbeddedEllipticCurveKeys>, RpcError> {
|
||||||
|
let Some(keys) = self
|
||||||
|
.0
|
||||||
|
.call::<Option<String>>(
|
||||||
|
"validator-sets/embedded_elliptic_curve_keys",
|
||||||
|
&format!(r#", "validator": {validator}, "network": {} "#, rpc_network(network)?),
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
EmbeddedEllipticCurveKeys::deserialize(
|
||||||
|
&mut hex::decode(keys)
|
||||||
|
.map_err(|_| {
|
||||||
|
RpcError::InvalidNode(
|
||||||
|
"validator's embedded elliptic curve keys weren't valid hex".to_string(),
|
||||||
|
)
|
||||||
|
})?
|
||||||
|
.as_slice(),
|
||||||
|
)
|
||||||
|
.map(Some)
|
||||||
|
.map_err(|_| {
|
||||||
|
RpcError::InvalidNode("validator's embedded elliptic curve keys weren't valid".to_string())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Create a transaction to set a validator set's keys.
|
/// Create a transaction to set a validator set's keys.
|
||||||
pub fn set_keys(
|
pub fn set_keys(
|
||||||
network: ExternalNetworkId,
|
network: ExternalNetworkId,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use std::{sync::Arc, ops::Deref, convert::AsRef, collections::HashSet};
|
use core::{ops::Deref, convert::AsRef, str::FromStr};
|
||||||
|
use std::{sync::Arc, collections::HashSet};
|
||||||
|
|
||||||
use rand_core::{RngCore, OsRng};
|
use rand_core::{RngCore, OsRng};
|
||||||
|
|
||||||
@@ -111,5 +112,74 @@ pub(crate) fn module<
|
|||||||
Ok(key_pair.map(|key_pair| hex::encode(borsh::to_vec(&key_pair).unwrap())))
|
Ok(key_pair.map(|key_pair| hex::encode(borsh::to_vec(&key_pair).unwrap())))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
module.register_method(
|
||||||
|
"validator-sets/current_validators",
|
||||||
|
|params, client, _ext| -> Result<_, Error> {
|
||||||
|
let Some(block_hash) = block_hash(&**client, ¶ms)? else {
|
||||||
|
Err(Error::InvalidStateReference)?
|
||||||
|
};
|
||||||
|
let network = network(¶ms)?;
|
||||||
|
let Ok(validators) = client.runtime_api().current_validators(block_hash, network) else {
|
||||||
|
Err(Error::Internal("couldn't fetch the current validators for the requested network"))?
|
||||||
|
};
|
||||||
|
Ok(
|
||||||
|
validators.map(|validators| validators.iter().map(ToString::to_string).collect::<Vec<_>>()),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
module.register_method(
|
||||||
|
"validator-sets/pending_slash_report",
|
||||||
|
|params, client, _ext| -> Result<_, Error> {
|
||||||
|
let Some(block_hash) = block_hash(&**client, ¶ms)? else {
|
||||||
|
Err(Error::InvalidStateReference)?
|
||||||
|
};
|
||||||
|
let Ok(network) = ExternalNetworkId::try_from(network(¶ms)?) else {
|
||||||
|
Err(Error::InvalidRequest(
|
||||||
|
"asking if a non-external validator set has a pending slash report",
|
||||||
|
))?
|
||||||
|
};
|
||||||
|
client
|
||||||
|
.runtime_api()
|
||||||
|
.pending_slash_report(block_hash, network)
|
||||||
|
.map_err(|_| Error::Internal("couldn't fetch if this network has a pending slash report"))
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
module.register_method(
|
||||||
|
"validator-sets/embedded_elliptic_curve_keys",
|
||||||
|
|params, client, _ext| -> Result<_, Error> {
|
||||||
|
let Some(block_hash) = block_hash(&**client, ¶ms)? else {
|
||||||
|
Err(Error::InvalidStateReference)?
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(sp_core::serde::Deserialize)]
|
||||||
|
#[serde(crate = "sp_core::serde")]
|
||||||
|
struct Validator {
|
||||||
|
validator: String,
|
||||||
|
}
|
||||||
|
let Ok(validator) = params.parse::<Validator>() else {
|
||||||
|
Err(Error::InvalidRequest(r#"missing `string` "validator" field"#))?
|
||||||
|
};
|
||||||
|
let Ok(validator) = SeraiAddress::from_str(&validator.validator) else {
|
||||||
|
Err(Error::InvalidRequest(r#"validator had an invalid address"#))?
|
||||||
|
};
|
||||||
|
|
||||||
|
let Ok(network) = ExternalNetworkId::try_from(network(¶ms)?) else {
|
||||||
|
Err(Error::InvalidRequest(
|
||||||
|
"asking for the embedded elliptic curve keys for a non-external network",
|
||||||
|
))?
|
||||||
|
};
|
||||||
|
let Ok(embedded_elliptic_curve_keys) =
|
||||||
|
client.runtime_api().embedded_elliptic_curve_keys(block_hash, validator, network)
|
||||||
|
else {
|
||||||
|
Err(Error::Internal("couldn't fetch the keys for the requested validator set"))?
|
||||||
|
};
|
||||||
|
Ok(embedded_elliptic_curve_keys.map(|embedded_elliptic_curve_keys| {
|
||||||
|
hex::encode(borsh::to_vec(&embedded_elliptic_curve_keys).unwrap())
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
module
|
module
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,10 +6,11 @@ extern crate alloc;
|
|||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use serai_abi::{
|
use serai_abi::{
|
||||||
primitives::{
|
primitives::{
|
||||||
crypto::{Public, SignedEmbeddedEllipticCurveKeys, KeyPair},
|
crypto::{Public, EmbeddedEllipticCurveKeys, SignedEmbeddedEllipticCurveKeys, KeyPair},
|
||||||
network_id::NetworkId,
|
network_id::{ExternalNetworkId, NetworkId},
|
||||||
validator_sets::{Session, ExternalValidatorSet, ValidatorSet},
|
validator_sets::{Session, ExternalValidatorSet, ValidatorSet},
|
||||||
balance::{Amount, Balance},
|
balance::{Amount, Balance},
|
||||||
|
address::SeraiAddress,
|
||||||
},
|
},
|
||||||
Event,
|
Event,
|
||||||
};
|
};
|
||||||
@@ -39,6 +40,12 @@ sp_api::decl_runtime_apis! {
|
|||||||
fn current_session(network: NetworkId) -> Option<Session>;
|
fn current_session(network: NetworkId) -> Option<Session>;
|
||||||
fn current_stake(network: NetworkId) -> Option<Amount>;
|
fn current_stake(network: NetworkId) -> Option<Amount>;
|
||||||
fn keys(set: ExternalValidatorSet) -> Option<KeyPair>;
|
fn keys(set: ExternalValidatorSet) -> Option<KeyPair>;
|
||||||
|
fn current_validators(network: NetworkId) -> Option<Vec<SeraiAddress>>;
|
||||||
|
fn pending_slash_report(network: ExternalNetworkId) -> bool;
|
||||||
|
fn embedded_elliptic_curve_keys(
|
||||||
|
validator: SeraiAddress,
|
||||||
|
network: ExternalNetworkId,
|
||||||
|
) -> Option<EmbeddedEllipticCurveKeys>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +190,7 @@ mod apis {
|
|||||||
unimplemented!("runtime is only implemented when WASM")
|
unimplemented!("runtime is only implemented when WASM")
|
||||||
}
|
}
|
||||||
fn validators(
|
fn validators(
|
||||||
network: serai_abi::primitives::network_id::NetworkId
|
network: NetworkId
|
||||||
) -> Vec<serai_abi::primitives::crypto::Public> {
|
) -> Vec<serai_abi::primitives::crypto::Public> {
|
||||||
unimplemented!("runtime is only implemented when WASM")
|
unimplemented!("runtime is only implemented when WASM")
|
||||||
}
|
}
|
||||||
@@ -196,6 +203,18 @@ mod apis {
|
|||||||
fn keys(set: ExternalValidatorSet) -> Option<KeyPair> {
|
fn keys(set: ExternalValidatorSet) -> Option<KeyPair> {
|
||||||
unimplemented!("runtime is only implemented when WASM")
|
unimplemented!("runtime is only implemented when WASM")
|
||||||
}
|
}
|
||||||
|
fn current_validators(network: NetworkId) -> Option<Vec<SeraiAddress>> {
|
||||||
|
unimplemented!("runtime is only implemented when WASM")
|
||||||
|
}
|
||||||
|
fn pending_slash_report(network: ExternalNetworkId) -> bool {
|
||||||
|
unimplemented!("runtime is only implemented when WASM")
|
||||||
|
}
|
||||||
|
fn embedded_elliptic_curve_keys(
|
||||||
|
validator: SeraiAddress,
|
||||||
|
network: ExternalNetworkId,
|
||||||
|
) -> Option<EmbeddedEllipticCurveKeys> {
|
||||||
|
unimplemented!("runtime is only implemented when WASM")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use sp_version::RuntimeVersion;
|
|||||||
|
|
||||||
use serai_abi::{
|
use serai_abi::{
|
||||||
primitives::{
|
primitives::{
|
||||||
|
crypto::EmbeddedEllipticCurveKeys,
|
||||||
network_id::{ExternalNetworkId, NetworkId},
|
network_id::{ExternalNetworkId, NetworkId},
|
||||||
balance::{Amount, ExternalBalance},
|
balance::{Amount, ExternalBalance},
|
||||||
validator_sets::{Session, ExternalValidatorSet, ValidatorSet},
|
validator_sets::{Session, ExternalValidatorSet, ValidatorSet},
|
||||||
@@ -582,6 +583,23 @@ sp_api::impl_runtime_apis! {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
fn current_validators(network: NetworkId) -> Option<Vec<SeraiAddress>> {
|
||||||
|
let session = ValidatorSets::current_session(network)?;
|
||||||
|
Some(
|
||||||
|
ValidatorSets::selected_validators(ValidatorSet { network, session })
|
||||||
|
.map(|(key, _key_shares)| SeraiAddress::from(key))
|
||||||
|
.collect()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
fn pending_slash_report(network: ExternalNetworkId) -> bool {
|
||||||
|
ValidatorSets::pending_slash_report(network)
|
||||||
|
}
|
||||||
|
fn embedded_elliptic_curve_keys(
|
||||||
|
validator: SeraiAddress,
|
||||||
|
network: ExternalNetworkId,
|
||||||
|
) -> Option<EmbeddedEllipticCurveKeys> {
|
||||||
|
ValidatorSets::embedded_elliptic_curve_keys(validator.into(), network)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
use sp_core::sr25519::Public;
|
use sp_core::sr25519::Public;
|
||||||
|
|
||||||
use serai_abi::primitives::{crypto::SignedEmbeddedEllipticCurveKeys, network_id::*};
|
use serai_abi::primitives::{
|
||||||
|
crypto::{
|
||||||
|
EmbeddedEllipticCurveKeys as EmbeddedEllipticCurveKeysStruct, SignedEmbeddedEllipticCurveKeys,
|
||||||
|
},
|
||||||
|
network_id::*,
|
||||||
|
};
|
||||||
|
|
||||||
use frame_support::storage::StorageDoubleMap;
|
use frame_support::storage::StorageDoubleMap;
|
||||||
|
|
||||||
@@ -11,8 +16,8 @@ pub(crate) trait EmbeddedEllipticCurveKeysStorage {
|
|||||||
type EmbeddedEllipticCurveKeys: StorageDoubleMap<
|
type EmbeddedEllipticCurveKeys: StorageDoubleMap<
|
||||||
ExternalNetworkId,
|
ExternalNetworkId,
|
||||||
Public,
|
Public,
|
||||||
serai_abi::primitives::crypto::EmbeddedEllipticCurveKeys,
|
EmbeddedEllipticCurveKeysStruct,
|
||||||
Query = Option<serai_abi::primitives::crypto::EmbeddedEllipticCurveKeys>,
|
Query = Option<EmbeddedEllipticCurveKeysStruct>,
|
||||||
>;
|
>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,6 +28,13 @@ pub(crate) trait EmbeddedEllipticCurveKeys {
|
|||||||
validator: Public,
|
validator: Public,
|
||||||
keys: SignedEmbeddedEllipticCurveKeys,
|
keys: SignedEmbeddedEllipticCurveKeys,
|
||||||
) -> Result<(), ()>;
|
) -> Result<(), ()>;
|
||||||
|
|
||||||
|
/// Get a validator's embedded elliptic curve keys, for an external network.
|
||||||
|
fn embedded_elliptic_curve_keys(
|
||||||
|
validator: Public,
|
||||||
|
network: ExternalNetworkId,
|
||||||
|
) -> Option<EmbeddedEllipticCurveKeysStruct>;
|
||||||
|
|
||||||
/// Check if a validator still needs to set embedded elliptic curve keys.
|
/// Check if a validator still needs to set embedded elliptic curve keys.
|
||||||
fn still_needs_to_set_embedded_elliptic_curve_keys(network: NetworkId, validator: Public)
|
fn still_needs_to_set_embedded_elliptic_curve_keys(network: NetworkId, validator: Public)
|
||||||
-> bool;
|
-> bool;
|
||||||
@@ -39,6 +51,14 @@ impl<S: EmbeddedEllipticCurveKeysStorage> EmbeddedEllipticCurveKeys for S {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a validator's embedded elliptic curve keys, for an external network.
|
||||||
|
fn embedded_elliptic_curve_keys(
|
||||||
|
validator: Public,
|
||||||
|
network: ExternalNetworkId,
|
||||||
|
) -> Option<EmbeddedEllipticCurveKeysStruct> {
|
||||||
|
S::EmbeddedEllipticCurveKeys::get(network, validator)
|
||||||
|
}
|
||||||
|
|
||||||
/// Check if a validator still needs to set embedded elliptic curve keys.
|
/// Check if a validator still needs to set embedded elliptic curve keys.
|
||||||
fn still_needs_to_set_embedded_elliptic_curve_keys(
|
fn still_needs_to_set_embedded_elliptic_curve_keys(
|
||||||
network: NetworkId,
|
network: NetworkId,
|
||||||
|
|||||||
@@ -32,7 +32,10 @@ mod pallet {
|
|||||||
|
|
||||||
use serai_abi::{
|
use serai_abi::{
|
||||||
primitives::{
|
primitives::{
|
||||||
crypto::{SignedEmbeddedEllipticCurveKeys, ExternalKey, KeyPair, Signature},
|
crypto::{
|
||||||
|
EmbeddedEllipticCurveKeys as EmbeddedEllipticCurveKeysStruct,
|
||||||
|
SignedEmbeddedEllipticCurveKeys, ExternalKey, KeyPair, Signature,
|
||||||
|
},
|
||||||
network_id::*,
|
network_id::*,
|
||||||
coin::*,
|
coin::*,
|
||||||
balance::*,
|
balance::*,
|
||||||
@@ -315,6 +318,19 @@ mod pallet {
|
|||||||
Abstractions::<T>::external_key(set)
|
Abstractions::<T>::external_key(set)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn pending_slash_report(network: ExternalNetworkId) -> bool {
|
||||||
|
Abstractions::<T>::waiting_for_slash_report(network).is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn embedded_elliptic_curve_keys(
|
||||||
|
validator: Public,
|
||||||
|
network: ExternalNetworkId,
|
||||||
|
) -> Option<EmbeddedEllipticCurveKeysStruct> {
|
||||||
|
<Abstractions<T> as crate::EmbeddedEllipticCurveKeys>::embedded_elliptic_curve_keys(
|
||||||
|
validator, network,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO
|
/* TODO
|
||||||
pub fn distribute_block_rewards(
|
pub fn distribute_block_rewards(
|
||||||
network: NetworkId,
|
network: NetworkId,
|
||||||
|
|||||||
Reference in New Issue
Block a user