shards 0.1.0

rust bindings and utility in order to use shards
Documentation
/* SPDX-License-Identifier: BSD-3-Clause */
/* Copyright © 2021 Fragcolor Pte. Ltd. */

use crate::shard::Shard;
use crate::shardsc::SHType_String;
use crate::core::do_blocking;
use crate::core::log;
use crate::core::registerShard;
use crate::types::common_type;
use crate::types::ClonedVar;
use crate::types::Context;
use crate::types::InstanceData;
use crate::types::ParamVar;
use crate::types::Parameters;
use crate::types::Seq;
use crate::types::Table;
use crate::types::Type;
use crate::types::BYTES_TYPES;
use crate::types::STRING_TYPES;
use crate::CString;
use crate::Types;
use crate::Var;
use core::time::Duration;
use sp_core::crypto::Pair;
use sp_core::ed25519;
use sp_core::sr25519;
use std::convert::TryFrom;
use std::convert::TryInto;
use std::ffi::CStr;

lazy_static! {
  static ref PK_TYPES: Vec<Type> = vec![common_type::bytes, common_type::string];
  static ref PARAMETERS: Parameters = vec![(
    cstr!("Key"),
    shccstr!("The private key to be used to sign the hashed message input."),
    vec![
      common_type::bytes,
      common_type::bytes_var,
      common_type::string,
      common_type::string_var
    ]
  )
    .into()];
  static ref SIG_PARAMETERS: Parameters = vec![(
    cstr!("Signature"),
    shccstr!(
      "The signature and recovery id generated signing the input message with the private key."
    ),
    vec![common_type::bytezs, common_type::bytess_var]
  )
    .into()];
}

fn get_key<T: Pair>(input: Var) -> Result<T, &'static str> {
  let key: Result<&[u8], &str> = input.as_ref().try_into();
  if let Ok(key) = key {
    T::from_seed_slice(key).map_err(|e| {
      shlog!("{:?}", e);
      "Failed to parse secret key"
    })
  } else {
    let key: Result<&str, &str> = input.as_ref().try_into();
    if let Ok(key) = key {
      T::from_string(key, None).map_err(|e| {
        shlog!("{:?}", e);
        "Failed to parse secret key"
      })
    } else {
      Err("Invalid key value")
    }
  }
}

macro_rules! add_signer {
  ($shard_name:ident, $name_str:literal, $hash:literal, $key_type:tt, $size:literal) => {
    #[derive(Default)]
    struct $shard_name {
      output: ClonedVar,
      key: ParamVar,
    }

    impl Shard for $shard_name {
      fn registerName() -> &'static str {
        cstr!($name_str)
      }

      fn hash() -> u32 {
        compile_time_crc32::crc32!($hash)
      }

      fn name(&mut self) -> &str {
        $name_str
      }

      fn inputTypes(&mut self) -> &std::vec::Vec<Type> {
        &BYTES_TYPES
      }

      fn outputTypes(&mut self) -> &std::vec::Vec<Type> {
        &BYTES_TYPES
      }

      fn parameters(&mut self) -> Option<&Parameters> {
        Some(&PARAMETERS)
      }

      fn setParam(&mut self, index: i32, value: &Var) {
        match index {
          0 => self.key.set_param(value),
          _ => unreachable!(),
        }
      }

      fn getParam(&mut self, index: i32) -> Var {
        match index {
          0 => self.key.get_param(),
          _ => unreachable!(),
        }
      }

      fn warmup(&mut self, context: &Context) -> Result<(), &str> {
        self.key.warmup(context);
        Ok(())
      }

      fn cleanup(&mut self) {
        self.key.cleanup();
      }

      fn activate(&mut self, _: &Context, input: &Var) -> Result<Var, &str> {
        let bytes: &[u8] = input.as_ref().try_into()?;

        let key = self.key.get();
        let key: $key_type::Pair = get_key(key)?;

        let signature: $key_type::Signature = key.sign(bytes);
        let signature: [u8; $size] = signature.0;

        self.output = signature[..].into();
        Ok(self.output.0)
      }
    }
  };
}

add_signer!(
  Sr25519Sign,
  "Sr25519.Sign",
  "Sr25519.Sign-rust-0x20200101",
  sr25519,
  64
);

add_signer!(
  Ed25519Sign,
  "Ed25519.Sign",
  "Ed25519.Sign-rust-0x20200101",
  ed25519,
  64
);

macro_rules! add_pub_key {
  ($shard_name:ident, $name_str:literal, $hash:literal, $key_type:tt, $size:literal) => {
    #[derive(Default)]
    struct $shard_name {
      output: ClonedVar,
      is_string: bool,
    }

    impl Shard for $shard_name {
      fn registerName() -> &'static str {
        cstr!($name_str)
      }

      fn hash() -> u32 {
        compile_time_crc32::crc32!($hash)
      }

      fn name(&mut self) -> &str {
        $name_str
      }

      fn inputTypes(&mut self) -> &std::vec::Vec<Type> {
        &PK_TYPES
      }

      fn outputTypes(&mut self) -> &std::vec::Vec<Type> {
        &BYTES_TYPES
      }

      fn activate(&mut self, _: &Context, input: &Var) -> Result<Var, &str> {
        let key: $key_type::Pair = get_key(*input)?;
        let key = key.public();
        let key: &[u8; $size] = key.as_array_ref();
        self.output = key[..].into();
        Ok(self.output.0)
      }
    }
  };
}

add_pub_key!(
  Sr25519PublicKey,
  "Sr25519.PublicKey",
  "Sr25519.PublicKey-rust-0x20200101",
  sr25519,
  32
);

add_pub_key!(
  Ed25519PublicKey,
  "Ed25519.PublicKey",
  "Ed25519.PublicKey-rust-0x20200101",
  ed25519,
  32
);

macro_rules! add_priv_key {
  ($shard_name:ident, $name_str:literal, $hash:literal, $key_type:tt, $size:literal) => {
    #[derive(Default)]
    struct $shard_name {
      output: ClonedVar,
      is_string: bool,
    }

    impl Shard for $shard_name {
      fn registerName() -> &'static str {
        cstr!($name_str)
      }

      fn hash() -> u32 {
        compile_time_crc32::crc32!($hash)
      }

      fn name(&mut self) -> &str {
        $name_str
      }

      fn inputTypes(&mut self) -> &std::vec::Vec<Type> {
        &STRING_TYPES
      }

      fn outputTypes(&mut self) -> &std::vec::Vec<Type> {
        &BYTES_TYPES
      }

      fn activate(&mut self, _: &Context, input: &Var) -> Result<Var, &str> {
        let key: &str = input.as_ref().try_into()?;
        let (_, seed) = $key_type::Pair::from_string_with_seed(key, None).map_err(|e| {
          shlog!("{:?}", e);
          "Failed to parse secret key mnemonic or string"
        })?;
        if let Some(seed) = seed {
          self.output = seed[..].into();
          Ok(self.output.0)
        } else {
          Err("No seed found")
        }
      }
    }
  };
}

add_priv_key!(
  Sr25519Seed,
  "Sr25519.Seed",
  "Sr25519.Seed-rust-0x20200101",
  sr25519,
  32
);

add_priv_key!(
  Ed25519Seed,
  "Ed25519.Seed",
  "Ed25519.Seed-rust-0x20200101",
  ed25519,
  32
);

pub fn registerShards() {
  registerShard::<Sr25519Sign>();
  registerShard::<Ed25519Sign>();
  registerShard::<Sr25519PublicKey>();
  registerShard::<Ed25519PublicKey>();
  registerShard::<Sr25519Seed>();
  registerShard::<Ed25519Seed>();
}