Skip to content

Commit

Permalink
Merge cb8befc into 21abae4
Browse files Browse the repository at this point in the history
  • Loading branch information
greenhat committed Oct 9, 2020
2 parents 21abae4 + cb8befc commit 9d2e0a5
Show file tree
Hide file tree
Showing 9 changed files with 225 additions and 48 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Expand Up @@ -72,7 +72,7 @@ matrix:

- name: build for iOS
os: osx
osx_image: xcode11.5
osx_image: xcode12
rust: stable
before_install:
- rustup target add aarch64-apple-ios x86_64-apple-ios
Expand Down
5 changes: 3 additions & 2 deletions README.md
Expand Up @@ -16,5 +16,6 @@ Bindings:

## Contributing
Contributions are very welcome! Checkout issues labeled ["help wanted" and "good first issue"](https://github.com/ergoplatform/sigma-rust/labels/help%20wanted)
We check code formatting and linter(`clippy`) as part of the CI process. It's better to set up your editor to run `rustfmt` on file save.
Feel free to disable specific linter rules in the source code when appropriate.
We check code formatting and linter(`clippy`) as part of the CI process. It's better to set up your editor to run `rustfmt` on file save. Feel free to disable specific linter rules in the source code when appropriate.

You are welcome to join the [Ergo Discord](https://discord.gg/kj7s7nb) and ask questions on `#sigma-rust` channel.
1 change: 0 additions & 1 deletion bindings/ergo-lib-c-core/Cargo.toml
Expand Up @@ -12,6 +12,5 @@ crate-type = ["lib"]

[dependencies]
ergo-lib = { version = "0.2.0", path = "../../ergo-lib" }

thiserror = "1"

5 changes: 2 additions & 3 deletions bindings/ergo-lib-c/Cargo.toml
Expand Up @@ -16,10 +16,9 @@ exclude = [
crate-type = ["staticlib"]

[dependencies]
ffi_helpers = "0.2"
ergo-lib = {version = "0.2.0", path = "../../ergo-lib"}
ergo-lib-c-core = {version = "0.1.0", path = "../ergo-lib-c-core"}


[build-dependencies]
cbindgen = "0.14"
serde = { version = "1.0", features = ["derive"] }
cbindgen = "0.15"
34 changes: 8 additions & 26 deletions bindings/ergo-lib-wasm/src/ast.rs
Expand Up @@ -6,6 +6,7 @@ use js_sys::Uint8Array;
use wasm_bindgen::prelude::*;

use crate::utils::I64;
use ergo_lib::ast::TryExtractFrom;

/// Ergo constant(evaluated) values
#[wasm_bindgen]
Expand Down Expand Up @@ -40,13 +41,7 @@ impl Constant {

/// Extract i32 value, returning error if wrong type
pub fn to_i32(&self) -> Result<i32, JsValue> {
match self.0.v {
ergo_lib::ast::ConstantVal::Int(v) => Ok(v),
_ => Err(JsValue::from_str(&format!(
"expected i32, found: {:?}",
self.0.v
))),
}
i32::try_extract_from(self.0.clone()).map_err(|e| JsValue::from_str(&format! {"{:?}", e}))
}

/// Create from i64
Expand All @@ -56,13 +51,9 @@ impl Constant {

/// Extract i64 value, returning error if wrong type
pub fn to_i64(&self) -> Result<I64, JsValue> {
match self.0.v {
ergo_lib::ast::ConstantVal::Long(v) => Ok(v.into()),
_ => Err(JsValue::from_str(&format!(
"expected i64, found: {:?}",
self.0.v
))),
}
i64::try_extract_from(self.0.clone())
.map_err(|e| JsValue::from_str(&format! {"{:?}", e}))
.map(I64::from)
}

/// Create from byte array
Expand All @@ -72,17 +63,8 @@ impl Constant {

/// Extract byte array, returning error if wrong type
pub fn to_byte_array(&self) -> Result<Uint8Array, JsValue> {
match self.0.v.clone() {
ergo_lib::ast::ConstantVal::Coll(ergo_lib::ast::ConstantColl::Primitive(
ergo_lib::ast::CollPrim::CollByte(coll_bytes),
)) => {
let u8_bytes: Vec<u8> = coll_bytes.into_iter().map(|b| b as u8).collect();
Ok(Uint8Array::from(u8_bytes.as_slice()))
}
_ => Err(JsValue::from_str(&format!(
"expected byte array, found: {:?}",
self.0.v
))),
}
Vec::<u8>::try_extract_from(self.0.clone())
.map(|v| Uint8Array::from(v.as_slice()))
.map_err(|e| JsValue::from_str(&format! {"{:?}", e}))
}
}
177 changes: 164 additions & 13 deletions ergo-lib/src/ast/constant.rs
@@ -1,14 +1,18 @@
use crate::chain::{Base16DecodedBytes, Base16EncodedBytes};
use crate::{
chain::ergo_box::ErgoBox,
serialization::{op_code::OpCode, SerializationError, SigmaSerializable},
serialization::{SerializationError, SigmaSerializable},
sigma_protocol::{dlog_group::EcPoint, sigma_boolean::SigmaProp},
types::{LiftIntoSType, SType},
};
#[cfg(feature = "json")]
use serde::{Deserialize, Serialize};
use std::convert::TryFrom;

mod constant_placeholder;

pub use constant_placeholder::*;

#[derive(PartialEq, Eq, Debug, Clone)]
/// Collection for primitive values (i.e byte array)
pub enum CollPrim {
Expand Down Expand Up @@ -271,22 +275,128 @@ impl Into<Constant> for Vec<i8> {
}
}

/// Placeholder for a constant in ErgoTree.
/// Underlying type is different from requested value type
#[derive(PartialEq, Eq, Debug, Clone)]
pub struct ConstantPlaceholder {
/// Zero based index in ErgoTree.constants array.
pub id: u32,
/// Type of the constant value
pub tpe: SType,
pub struct TryExtractFromError(String);

/// Extract underlying value if type matches
pub trait TryExtractFrom<T>: Sized {
/// Extract the value or return an error if type does not match
fn try_extract_from(c: T) -> Result<Self, TryExtractFromError>;
}

impl TryExtractFrom<ConstantVal> for bool {
fn try_extract_from(cv: ConstantVal) -> Result<bool, TryExtractFromError> {
match cv {
ConstantVal::Boolean(v) => Ok(v),
_ => Err(TryExtractFromError(format!(
"expected bool, found {:?}",
cv
))),
}
}
}

impl TryExtractFrom<ConstantVal> for i8 {
fn try_extract_from(cv: ConstantVal) -> Result<i8, TryExtractFromError> {
match cv {
ConstantVal::Byte(v) => Ok(v),
_ => Err(TryExtractFromError(format!("expected i8, found {:?}", cv))),
}
}
}

impl TryExtractFrom<ConstantVal> for i16 {
fn try_extract_from(cv: ConstantVal) -> Result<i16, TryExtractFromError> {
match cv {
ConstantVal::Short(v) => Ok(v),
_ => Err(TryExtractFromError(format!("expected i16, found {:?}", cv))),
}
}
}

impl TryExtractFrom<ConstantVal> for i32 {
fn try_extract_from(cv: ConstantVal) -> Result<i32, TryExtractFromError> {
match cv {
ConstantVal::Int(v) => Ok(v),
_ => Err(TryExtractFromError(format!("expected i32, found {:?}", cv))),
}
}
}

impl TryExtractFrom<ConstantVal> for i64 {
fn try_extract_from(cv: ConstantVal) -> Result<i64, TryExtractFromError> {
match cv {
ConstantVal::Long(v) => Ok(v),
_ => Err(TryExtractFromError(format!("expected i64, found {:?}", cv))),
}
}
}

impl ConstantPlaceholder {
/// OpCode value
pub const OP_CODE: OpCode = OpCode::CONSTANT_PLACEHOLDER;
impl TryExtractFrom<ConstantVal> for EcPoint {
fn try_extract_from(cv: ConstantVal) -> Result<EcPoint, TryExtractFromError> {
match cv {
ConstantVal::GroupElement(v) => Ok(*v),
_ => Err(TryExtractFromError(format!(
"expected EcPoint, found {:?}",
cv
))),
}
}
}

/// OpCode for the serialization
pub fn op_code(&self) -> OpCode {
OpCode::CONSTANT_PLACEHOLDER
impl TryExtractFrom<ConstantVal> for SigmaProp {
fn try_extract_from(cv: ConstantVal) -> Result<SigmaProp, TryExtractFromError> {
match cv {
ConstantVal::SigmaProp(v) => Ok(*v),
_ => Err(TryExtractFromError(format!(
"expected SigmaProp, found {:?}",
cv
))),
}
}
}

impl<T: TryExtractFrom<ConstantVal>> TryExtractFrom<Constant> for T {
fn try_extract_from(cv: Constant) -> Result<Self, TryExtractFromError> {
T::try_extract_from(cv.v)
}
}

impl<T: TryExtractFrom<ConstantVal> + StoredNonPrimitive + LiftIntoSType> TryExtractFrom<Constant>
for Vec<T>
{
fn try_extract_from(c: Constant) -> Result<Self, TryExtractFromError> {
match c.v {
ConstantVal::Coll(ConstantColl::NonPrimitive { elem_tpe: _, v }) => {
v.into_iter().map(T::try_extract_from).collect()
}
_ => Err(TryExtractFromError(format!(
"expected {:?}, found {:?}",
std::any::type_name::<Self>(),
c.v
))),
}
}
}

impl TryExtractFrom<Constant> for Vec<i8> {
fn try_extract_from(c: Constant) -> Result<Self, TryExtractFromError> {
match c.v {
ConstantVal::Coll(ConstantColl::Primitive(CollPrim::CollByte(bs))) => Ok(bs),
_ => Err(TryExtractFromError(format!(
"expected {:?}, found {:?}",
std::any::type_name::<Self>(),
c.v
))),
}
}
}

impl TryExtractFrom<Constant> for Vec<u8> {
fn try_extract_from(cv: Constant) -> Result<Self, TryExtractFromError> {
use crate::util::FromVecI8;
Vec::<i8>::try_extract_from(cv).map(Vec::<u8>::from_vec_i8)
}
}

Expand Down Expand Up @@ -317,4 +427,45 @@ mod tests {
.boxed()
}
}

proptest! {

#[test]
fn test_try_extract_from(c in any::<Constant>()) {
// let c = force_any_val::<Constant>();
match c.clone().tpe {
SType::SBoolean => {
let _ = bool::try_extract_from(c).unwrap();
}
SType::SByte => {
let _ = i8::try_extract_from(c).unwrap();
}
SType::SShort => {
let _ = i16::try_extract_from(c).unwrap();
}
SType::SInt => {
let _ = i32::try_extract_from(c).unwrap();
}
SType::SLong => {
let _ = i64::try_extract_from(c).unwrap();
}
SType::SGroupElement => {
let _ = EcPoint::try_extract_from(c).unwrap();
}
SType::SSigmaProp => {
let _ = SigmaProp::try_extract_from(c).unwrap();
}
SType::SColl(elem_type) => {
match *elem_type {
SType::SByte => { let _ = Vec::<i8>::try_extract_from(c).unwrap(); }
SType::SShort => { let _ = Vec::<i16>::try_extract_from(c).unwrap(); }
SType::SInt => { let _ = Vec::<i32>::try_extract_from(c).unwrap(); }
SType::SLong => { let _ = Vec::<i64>::try_extract_from(c).unwrap(); }
_ => todo!()
}
}
_ => todo!(),
};
}
}
}
21 changes: 21 additions & 0 deletions ergo-lib/src/ast/constant/constant_placeholder.rs
@@ -0,0 +1,21 @@
use crate::serialization::op_code::OpCode;
use crate::types::SType;

/// Placeholder for a constant in ErgoTree.
#[derive(PartialEq, Eq, Debug, Clone)]
pub struct ConstantPlaceholder {
/// Zero based index in ErgoTree.constants array.
pub id: u32,
/// Type of the constant value
pub tpe: SType,
}

impl ConstantPlaceholder {
/// OpCode value
pub const OP_CODE: OpCode = OpCode::CONSTANT_PLACEHOLDER;

/// OpCode for the serialization
pub fn op_code(&self) -> OpCode {
OpCode::CONSTANT_PLACEHOLDER
}
}
4 changes: 2 additions & 2 deletions ergo-lib/src/serialization/data.rs
@@ -1,6 +1,7 @@
use crate::serialization::{
sigma_byte_reader::SigmaByteRead, SerializationError, SigmaSerializable,
};
use crate::util::AsVecU8;
use crate::{
ast::ConstantVal,
ast::ConstantVal::*,
Expand Down Expand Up @@ -33,8 +34,7 @@ impl DataSerializer {
Coll(ct) => match ct {
ConstantColl::Primitive(CollPrim::CollByte(b)) => {
w.put_usize_as_u16(b.len())?;
let ba: Vec<u8> = b.iter().map(|v| *v as u8).collect();
w.write_all(&ba[..])
w.write_all(b.clone().as_vec_u8().as_slice())
}
ConstantColl::NonPrimitive { elem_tpe: _, v } => {
w.put_usize_as_u16(v.len())?;
Expand Down
24 changes: 24 additions & 0 deletions ergo-lib/src/util.rs
Expand Up @@ -17,3 +17,27 @@ impl<T> IntoOption<T> for CtOption<T> {
}
}
}

/// Vec<i8> to Vec<u8> conversion
pub trait FromVecI8 {
/// Convert Vec<i8> to Vec<u8>
fn from_vec_i8(bs: Vec<i8>) -> Self;
}

impl FromVecI8 for Vec<u8> {
fn from_vec_i8(bs: Vec<i8>) -> Self {
bs.iter().map(|b| *b as u8).collect()
}
}

/// Convert Vec<i8> to Vec<u8>
pub trait AsVecU8 {
/// Returns as Vec<u8>
fn as_vec_u8(self) -> Vec<u8>;
}

impl AsVecU8 for Vec<i8> {
fn as_vec_u8(self) -> Vec<u8> {
Vec::<u8>::from_vec_i8(self)
}
}

0 comments on commit 9d2e0a5

Please sign in to comment.