sdk_common/src/network.rs

216 lines
5.7 KiB
Rust

use std::collections::HashMap;
use anyhow::Result;
use rand::{thread_rng, RngCore};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use sp_client::bitcoin::consensus::serialize;
use sp_client::bitcoin::hex::DisplayHex;
use sp_client::bitcoin::{OutPoint, Transaction};
use tsify::Tsify;
use crate::error::AnkError;
use crate::pcd::{Member, RoleDefinition};
use crate::process::Process;
use crate::signature::Proof;
#[derive(Debug, Serialize, Deserialize, Tsify)]
#[tsify(into_wasm_abi, from_wasm_abi)]
pub enum AnkFlag {
NewTx,
Faucet,
Cipher,
Commit,
Handshake,
Unknown,
}
impl From<&str> for AnkFlag {
fn from(value: &str) -> Self {
match value {
"NewTx" => Self::NewTx,
"Faucet" => Self::Faucet,
"Cipher" => Self::Cipher,
"Commit" => Self::Commit,
"Handshake" => Self::Handshake,
_ => Self::Unknown,
}
}
}
impl From<String> for AnkFlag {
fn from(value: String) -> Self {
(&value[..]).into()
}
}
impl AnkFlag {
pub fn new_from_byte(byte: u8) -> Self {
match byte {
0 => Self::NewTx,
1 => Self::Faucet,
2 => Self::Cipher,
3 => Self::Commit,
4 => Self::Handshake,
_ => Self::Unknown,
}
}
pub fn as_str(&self) -> &str {
match self {
Self::NewTx => "NewTx",
Self::Faucet => "Faucet",
Self::Cipher => "Cipher",
Self::Commit => "Commit",
Self::Handshake => "Handshake",
Self::Unknown => "Unknown",
}
}
}
/// Message sent to the server to commit some state in a transaction
/// Client must first send a commit message with empty validation_tokens
/// Relay will ignore a commit message for an update he's not aware of that also bears validation_tokens
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Tsify)]
#[tsify(into_wasm_abi, from_wasm_abi)]
pub struct CommitMessage {
pub init_tx: String, // Can be tx or txid of the first transaction of the chain, which is maybe not ideal
pub pcd_commitment: Value, // map of field <=> hash of the clear value
pub roles: HashMap<String, RoleDefinition>, // Can be hashed and compared with the value above
pub validation_tokens: Vec<Proof>,
pub error: Option<AnkError>,
}
impl CommitMessage {
/// Create a new commitment message for the first transaction of the chain
/// init_tx must be the hex string of the transaction
/// validation_tokens must be empty
pub fn new_first_commitment(
transaction: Transaction,
pcd_commitment: Value,
roles: HashMap<String, RoleDefinition>,
) -> Self {
Self {
init_tx: serialize(&transaction).to_lower_hex_string(),
pcd_commitment,
roles,
validation_tokens: vec![],
error: None,
}
}
/// Create a new commitment message for an update transaction
/// init_tx must be the hex string of the txid of the first commitment transaction
/// validation_tokens must be empty
pub fn new_update_commitment(
init_tx: OutPoint,
pcd_commitment: Value,
roles: HashMap<String, RoleDefinition>,
) -> Self {
Self {
init_tx: init_tx.to_string(),
pcd_commitment,
roles,
validation_tokens: vec![],
error: None,
}
}
/// Set the validation tokens for a pending commitment
pub fn set_validation_tokens(&mut self, validation_tokens: Vec<Proof>) {
self.validation_tokens = validation_tokens;
}
}
#[derive(Debug, Serialize, Deserialize, Tsify)]
#[tsify(into_wasm_abi, from_wasm_abi)]
pub struct FaucetMessage {
pub sp_address: String,
pub commitment: String,
pub error: Option<AnkError>,
}
impl FaucetMessage {
pub fn new(sp_address: String) -> Self {
let mut buf = [0u8; 32];
thread_rng().fill_bytes(&mut buf);
Self {
sp_address,
commitment: buf.to_lower_hex_string(),
error: None,
}
}
pub fn to_string(&self) -> String {
serde_json::to_string(self).unwrap()
}
}
#[derive(Debug, PartialEq, Serialize, Deserialize, Tsify)]
#[tsify(into_wasm_abi, from_wasm_abi)]
pub struct NewTxMessage {
pub transaction: String,
pub tweak_data: Option<String>,
pub error: Option<AnkError>,
}
impl NewTxMessage {
pub fn new(transaction: String, tweak_data: Option<String>) -> Self {
Self {
transaction,
tweak_data,
error: None,
}
}
pub fn to_string(&self) -> String {
serde_json::to_string(self).unwrap()
}
}
#[derive(Debug, PartialEq, Serialize, Deserialize, Tsify)]
#[tsify(into_wasm_abi, from_wasm_abi)]
pub struct HandshakeMessage {
pub sp_address: String,
pub peers_list: HashMap<Member, OutPoint>,
pub processes_list: HashMap<OutPoint, Process>,
}
impl HandshakeMessage {
pub fn new(sp_address: String, peers_list: HashMap<Member, OutPoint>, processes_list: HashMap<OutPoint, Process>) -> Self {
Self {
sp_address,
peers_list,
processes_list,
}
}
pub fn to_string(&self) -> String {
serde_json::to_string(self).unwrap()
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Envelope {
pub flag: AnkFlag,
pub content: String,
}
impl Envelope {
pub fn new(flag: AnkFlag, raw: &str) -> Self {
Self {
flag,
content: raw.into(),
}
}
pub fn from_string(json: &str) -> Result<Self> {
let res: Self = serde_json::from_str(json)?;
Ok(res)
}
pub fn to_string(&self) -> String {
serde_json::to_string(self).unwrap()
}
}