mirror of
https://github.com/serai-dex/serai.git
synced 2024-12-23 03:59:22 +00:00
Start defining the coordinator
This commit is contained in:
parent
51bf51ae1e
commit
eafd054296
7 changed files with 135 additions and 19 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1305,10 +1305,12 @@ name = "coordinator"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"blake2",
|
"blake2",
|
||||||
|
"log",
|
||||||
"modular-frost",
|
"modular-frost",
|
||||||
"processor-messages",
|
"processor-messages",
|
||||||
"rand_core 0.6.4",
|
"rand_core 0.6.4",
|
||||||
"serai-client",
|
"serai-client",
|
||||||
|
"serai-db",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tributary-chain",
|
"tributary-chain",
|
||||||
]
|
]
|
||||||
|
|
|
@ -14,13 +14,19 @@ all-features = true
|
||||||
rustdoc-args = ["--cfg", "docsrs"]
|
rustdoc-args = ["--cfg", "docsrs"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
log = "0.4"
|
||||||
|
|
||||||
blake2 = "0.10"
|
blake2 = "0.10"
|
||||||
|
|
||||||
frost = { package = "modular-frost", path = "../crypto/frost" }
|
frost = { package = "modular-frost", path = "../crypto/frost" }
|
||||||
|
|
||||||
|
serai-db = { path = "../common/db" }
|
||||||
|
|
||||||
processor-messages = { package = "processor-messages", path = "../processor/messages" }
|
processor-messages = { package = "processor-messages", path = "../processor/messages" }
|
||||||
tributary = { package = "tributary-chain", path = "./tributary" }
|
tributary = { package = "tributary-chain", path = "./tributary" }
|
||||||
|
|
||||||
|
serai-client = { path = "../substrate/client", features = ["serai"] }
|
||||||
|
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
|
@ -1,7 +1,33 @@
|
||||||
|
#![allow(dead_code)]
|
||||||
|
#![allow(unused_variables)]
|
||||||
|
#![allow(unused_mut)]
|
||||||
|
|
||||||
|
use serai_db::Db;
|
||||||
|
|
||||||
|
use serai_client::Serai;
|
||||||
|
|
||||||
mod transaction;
|
mod transaction;
|
||||||
|
mod substrate;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
|
async fn run<D: Db>(db: D, serai: Serai) {
|
||||||
|
let mut last_substrate_block = 0; // TODO: Load from DB
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match substrate::handle_new_blocks(&serai, &mut last_substrate_block).await {
|
||||||
|
Ok(()) => {}
|
||||||
|
Err(e) => log::error!("couldn't communicate with serai node: {e}"),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle all messages from tributaries
|
||||||
|
|
||||||
|
// Handle all messages from processors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {}
|
async fn main() {
|
||||||
|
// Open the database
|
||||||
|
}
|
||||||
|
|
52
coordinator/src/substrate.rs
Normal file
52
coordinator/src/substrate.rs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
use serai_client::{SeraiError, Block, Serai};
|
||||||
|
|
||||||
|
async fn handle_block(serai: &Serai, block: Block) -> Result<Vec<()>, SeraiError> {
|
||||||
|
let hash = block.hash();
|
||||||
|
let mut actions = vec![];
|
||||||
|
|
||||||
|
// If a new validator set was activated, create tributary/inform processor to do a DKG
|
||||||
|
for new_set in serai.get_new_set_events(hash).await? {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a key pair was confirmed, inform the processor
|
||||||
|
for key_gen in serai.get_key_gen_events(hash).await? {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
// If batch, tell processor of block acknowledged/burns
|
||||||
|
for new_set in serai.get_batch_events(hash).await? {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(actions)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn handle_new_blocks(
|
||||||
|
serai: &Serai,
|
||||||
|
last_substrate_block: &mut u64,
|
||||||
|
) -> Result<(), SeraiError> {
|
||||||
|
// Check if there's been a new Substrate block
|
||||||
|
let latest = serai.get_latest_block().await?;
|
||||||
|
let latest_number = latest.number();
|
||||||
|
if latest_number == *last_substrate_block {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let mut latest = Some(latest);
|
||||||
|
|
||||||
|
for b in (*last_substrate_block + 1) ..= latest_number {
|
||||||
|
let actions = handle_block(
|
||||||
|
serai,
|
||||||
|
if b == latest_number {
|
||||||
|
latest.take().unwrap()
|
||||||
|
} else {
|
||||||
|
serai.get_block_by_number(b).await?.unwrap()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
// TODO: Handle actions, update the DB
|
||||||
|
*last_substrate_block += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -16,7 +16,7 @@ use subxt::{
|
||||||
extrinsic_params::{BaseExtrinsicParams, BaseExtrinsicParamsBuilder},
|
extrinsic_params::{BaseExtrinsicParams, BaseExtrinsicParamsBuilder},
|
||||||
},
|
},
|
||||||
tx::{Signer, Payload, TxClient},
|
tx::{Signer, Payload, TxClient},
|
||||||
rpc::types::ChainBlock,
|
rpc::types::{ChainBlock, ChainBlockExtrinsic},
|
||||||
Config as SubxtConfig, OnlineClient,
|
Config as SubxtConfig, OnlineClient,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -56,7 +56,32 @@ impl SubxtConfig for SeraiConfig {
|
||||||
type ExtrinsicParams = BaseExtrinsicParams<SeraiConfig, Tip>;
|
type ExtrinsicParams = BaseExtrinsicParams<SeraiConfig, Tip>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Block = ChainBlock<SeraiConfig>;
|
#[derive(Debug)]
|
||||||
|
pub struct Block(ChainBlock<SeraiConfig>);
|
||||||
|
impl Block {
|
||||||
|
pub fn hash(&self) -> [u8; 32] {
|
||||||
|
self.0.header.hash().into()
|
||||||
|
}
|
||||||
|
pub fn number(&self) -> u64 {
|
||||||
|
self.0.header.number
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn header(&self) -> &Header {
|
||||||
|
&self.0.header
|
||||||
|
}
|
||||||
|
pub fn transactions(&self) -> &[ChainBlockExtrinsic] {
|
||||||
|
&self.0.extrinsics
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for Block {
|
||||||
|
fn clone(&self) -> Block {
|
||||||
|
Block(ChainBlock::<SeraiConfig> {
|
||||||
|
header: self.0.header.clone(),
|
||||||
|
extrinsics: self.0.extrinsics.clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum SeraiError {
|
pub enum SeraiError {
|
||||||
|
@ -120,6 +145,19 @@ impl Serai {
|
||||||
Ok(self.0.rpc().finalized_head().await.map_err(SeraiError::RpcError)?.into())
|
Ok(self.0.rpc().finalized_head().await.map_err(SeraiError::RpcError)?.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_latest_block(&self) -> Result<Block, SeraiError> {
|
||||||
|
Ok(Block(
|
||||||
|
self
|
||||||
|
.0
|
||||||
|
.rpc()
|
||||||
|
.block(Some(self.0.rpc().finalized_head().await.map_err(SeraiError::RpcError)?))
|
||||||
|
.await
|
||||||
|
.map_err(SeraiError::RpcError)?
|
||||||
|
.ok_or(SeraiError::InvalidNode)?
|
||||||
|
.block,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
// There is no provided method for this
|
// There is no provided method for this
|
||||||
// TODO: Add one to Serai
|
// TODO: Add one to Serai
|
||||||
pub async fn is_finalized(&self, header: &Header) -> Result<Option<bool>, SeraiError> {
|
pub async fn is_finalized(&self, header: &Header) -> Result<Option<bool>, SeraiError> {
|
||||||
|
@ -169,7 +207,7 @@ impl Serai {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Some(res.block))
|
Ok(Some(Block(res.block)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ideally, this would be get_block_hash, not get_block_by_number
|
// Ideally, this would be get_block_hash, not get_block_by_number
|
||||||
|
|
|
@ -2,7 +2,7 @@ use core::time::Duration;
|
||||||
|
|
||||||
use tokio::time::sleep;
|
use tokio::time::sleep;
|
||||||
|
|
||||||
use serai_client::subxt::{config::Header, utils::Encoded};
|
use serai_client::subxt::utils::Encoded;
|
||||||
|
|
||||||
use crate::common::serai;
|
use crate::common::serai;
|
||||||
|
|
||||||
|
@ -10,13 +10,8 @@ use crate::common::serai;
|
||||||
pub async fn publish_tx(tx: &Encoded) -> [u8; 32] {
|
pub async fn publish_tx(tx: &Encoded) -> [u8; 32] {
|
||||||
let serai = serai().await;
|
let serai = serai().await;
|
||||||
|
|
||||||
let mut latest = serai
|
let mut latest =
|
||||||
.get_block(serai.get_latest_block_hash().await.unwrap())
|
serai.get_block(serai.get_latest_block_hash().await.unwrap()).await.unwrap().unwrap().number();
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.unwrap()
|
|
||||||
.header
|
|
||||||
.number();
|
|
||||||
|
|
||||||
serai.publish(tx).await.unwrap();
|
serai.publish(tx).await.unwrap();
|
||||||
|
|
||||||
|
@ -42,9 +37,9 @@ pub async fn publish_tx(tx: &Encoded) -> [u8; 32] {
|
||||||
block.unwrap()
|
block.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
for extrinsic in block.extrinsics {
|
for transaction in block.transactions() {
|
||||||
if extrinsic.0 == tx.0[2 ..] {
|
if transaction.0 == tx.0[2 ..] {
|
||||||
return block.header.hash().into();
|
return block.hash();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ use serai_client::{
|
||||||
primitives::{Session, ValidatorSet},
|
primitives::{Session, ValidatorSet},
|
||||||
ValidatorSetsEvent,
|
ValidatorSetsEvent,
|
||||||
},
|
},
|
||||||
subxt::config::Header,
|
|
||||||
Serai,
|
Serai,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -38,9 +37,7 @@ serai_test!(
|
||||||
// Make sure the genesis is as expected
|
// Make sure the genesis is as expected
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
serai
|
serai
|
||||||
.get_new_set_events(
|
.get_new_set_events(serai.get_block_by_number(0).await.unwrap().unwrap().hash())
|
||||||
serai.get_block_by_number(0).await.unwrap().unwrap().header.hash().into()
|
|
||||||
)
|
|
||||||
.await
|
.await
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
[BITCOIN_NET_ID, ETHEREUM_NET_ID, MONERO_NET_ID]
|
[BITCOIN_NET_ID, ETHEREUM_NET_ID, MONERO_NET_ID]
|
||||||
|
|
Loading…
Reference in a new issue