added report and airdrop

This commit is contained in:
ghe0 2025-04-24 02:47:52 +03:00
parent 71cc0a8d82
commit a8cf515061
Signed by: ghe0
GPG Key ID: 451028EE56A0FBB4
2 changed files with 90 additions and 58 deletions

@ -51,36 +51,6 @@ pub async fn migration0(old_data: &old_brain::BrainData) -> surrealdb::Result<()
Ok(())
}
pub async fn account(address: &str) -> Result<Account, Error> {
let id = (ACCOUNT, address);
let account: Option<Account> = DB.select(id).await?;
let account = match account {
Some(account) => account,
None => {
Account { id: id.into(), balance: 0, tmp_locked: 0, escrow: 0, email: String::new() }
}
};
Ok(account)
}
// I am not deleting this example cause I might need it later.
//
// async fn get_wallet_contracts() -> surrealdb::Result<Vec<Wallet>> {
// let mut result = DB
// .query("select *, ->contract.* from wallet:address1;")
// .await?;
// let wallets: Vec<Wallet> = result.take(0)?;
// Ok(wallets)
// }
//
// #[derive(Debug, Serialize, Deserialize)]
// pub struct Wallet {
// balance: u64,
// id: RecordId,
// #[serde(rename = "->contract", default)]
// contracts: Vec<Contract>,
// }
#[derive(Debug, Serialize, Deserialize)]
pub struct Account {
pub id: RecordId,
@ -90,6 +60,28 @@ pub struct Account {
pub email: String,
}
impl Account {
pub async fn get(address: &str) -> Result<Self, Error> {
let id = (ACCOUNT, address);
let account: Option<Self> = DB.select(id).await?;
let account = match account {
Some(account) => account,
None => {
Self { id: id.into(), balance: 0, tmp_locked: 0, escrow: 0, email: String::new() }
}
};
Ok(account)
}
pub async fn airdrop(account: &str, tokens: u64) -> Result<(), Error> {
let tokens = tokens.saturating_mul(1_000_000_000);
let _ = DB
.query(format!("upsert account:{account} SET balance = (balance || 0) + {tokens};"))
.await?;
Ok(())
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct VmNode {
pub id: RecordId,
@ -291,7 +283,6 @@ pub struct Kick {
#[derive(Debug, Serialize, Deserialize)]
pub struct Report {
id: RecordId,
#[serde(rename = "in")]
from_account: RecordId,
#[serde(rename = "out")]
@ -300,6 +291,17 @@ pub struct Report {
reason: String,
}
impl Report {
// TODO: test this functionality and remove this comment
pub async fn create(from_account: RecordId, to_node: RecordId, reason: String) -> Result<(), Error> {
let _: Vec<Self> = DB
.insert("report")
.relation(Report { from_account, to_node, created_at: Datetime::default(), reason })
.await?;
Ok(())
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct OperatorRelation {
#[serde(rename = "in")]

@ -95,29 +95,25 @@ impl BrainGeneralCli for BrainGeneralCliMock {
async fn get_balance(&self, req: Request<Pubkey>) -> Result<Response<AccountBalance>, Status> {
let req = check_sig_from_req(req)?;
Ok(Response::new(db::account(&req.pubkey).await?.into()))
Ok(Response::new(db::Account::get(&req.pubkey).await?.into()))
}
async fn report_node(&self, req: Request<ReportNodeReq>) -> Result<Response<Empty>, Status> {
let _req = check_sig_from_req(req)?;
todo!();
// match self.data.find_any_contract_by_uuid(&req.contract) {
// Ok((Some(vm_contract), _))
// if vm_contract.admin_pubkey == req.admin_pubkey
// && vm_contract.node_pubkey == req.node_pubkey =>
// {
// ()
// }
// Ok((_, Some(app_contract)))
// if app_contract.admin_pubkey == req.admin_pubkey
// && app_contract.node_pubkey == req.node_pubkey =>
// {
// ()
// }
// _ => return Err(Status::unauthenticated("No contract found by this ID.")),
// };
// self.data.report_any_node(req.admin_pubkey, &req.node_pubkey, req.reason);
// Ok(Response::new(Empty {}))
let req = check_sig_from_req(req)?;
let (account, node) = match db::VmContractWithNode::get_by_uuid(&req.contract).await? {
Some(vm_contract)
if vm_contract.admin.key().to_string() == req.admin_pubkey
&& vm_contract.vm_node.id.key().to_string() == req.node_pubkey =>
{
(vm_contract.admin, vm_contract.vm_node.id)
}
_ => {
// TODO: Hey, Noor! Please add app contract here.
return Err(Status::unauthenticated("No contract found by this ID."));
}
};
db::Report::create(account, node, req.reason).await?;
Ok(Response::new(Empty {}))
}
async fn list_operators(
@ -178,12 +174,11 @@ impl BrainGeneralCli for BrainGeneralCliMock {
// admin commands
async fn airdrop(&self, _req: Request<AirdropReq>) -> Result<Response<Empty>, Status> {
todo!();
// check_admin_key(&req)?;
// let req = check_sig_from_req(req)?;
// self.data.give_airdrop(&req.pubkey, req.tokens);
// Ok(Response::new(Empty {}))
async fn airdrop(&self, req: Request<AirdropReq>) -> Result<Response<Empty>, Status> {
check_admin_key(&req)?;
let req = check_sig_from_req(req)?;
db::Account::airdrop(&req.pubkey, req.tokens).await?;
Ok(Response::new(Empty {}))
}
async fn slash(&self, _req: Request<SlashReq>) -> Result<Response<Empty>, Status> {
@ -420,13 +415,26 @@ macro_rules! impl_pubkey_getter {
impl_pubkey_getter!(Pubkey, pubkey);
impl_pubkey_getter!(NewVmReq, admin_pubkey);
impl_pubkey_getter!(DeleteVmReq, admin_pubkey);
impl_pubkey_getter!(ReportNodeReq, admin_pubkey);
impl_pubkey_getter!(UpdateVmReq, admin_pubkey);
impl_pubkey_getter!(ExtendVmReq, admin_pubkey);
impl_pubkey_getter!(ReportNodeReq, admin_pubkey);
impl_pubkey_getter!(ListVmContractsReq, wallet);
impl_pubkey_getter!(RegisterVmNodeReq, node_pubkey);
impl_pubkey_getter!(RegOperatorReq, pubkey);
impl_pubkey_getter!(KickReq, operator_wallet);
impl_pubkey_getter!(BanUserReq, operator_wallet);
impl_pubkey_getter!(VmNodeFilters);
impl_pubkey_getter!(Empty);
impl_pubkey_getter!(AirdropReq);
impl_pubkey_getter!(SlashReq);
// impl_pubkey_getter!(NewAppReq, admin_pubkey);
// impl_pubkey_getter!(DelAppReq, admin_pubkey);
// impl_pubkey_getter!(ListAppContractsReq, admin_pubkey);
//
// impl_pubkey_getter!(RegisterAppNodeReq);
// impl_pubkey_getter!(AppNodeFilters);
fn check_sig_from_req<T: std::fmt::Debug + PubkeyGetter>(req: Request<T>) -> Result<T, Status> {
let time = match req.metadata().get("timestamp") {
@ -490,3 +498,25 @@ fn check_sig_from_req<T: std::fmt::Debug + PubkeyGetter>(req: Request<T>) -> Res
}
Ok(req)
}
const ADMIN_ACCOUNTS: &[&str] = &[
"x52w7jARC5erhWWK65VZmjdGXzBK6ZDgfv1A283d8XK",
"FHuecMbeC1PfjkW2JKyoicJAuiU7khgQT16QUB3Q1XdL",
"H21Shi4iE7vgfjWEQNvzmpmBMJSaiZ17PYUcdNoAoKNc",
];
fn check_admin_key<T>(req: &Request<T>) -> Result<(), Status> {
let pubkey = match req.metadata().get("pubkey") {
Some(p) => p.clone(),
None => return Err(Status::unauthenticated("pubkey not found in metadata.")),
};
let pubkey = pubkey
.to_str()
.map_err(|_| Status::unauthenticated("could not parse pubkey metadata to str"))?;
if !ADMIN_ACCOUNTS.contains(&pubkey) {
return Err(Status::unauthenticated("This operation is reserved to admin accounts"));
}
Ok(())
}