Skip to content

Commit

Permalink
Merge pull request #2 from redstone-finance/radix
Browse files Browse the repository at this point in the history
feat: added extension for Radix
  • Loading branch information
Lukasz2891 authored Sep 23, 2024
2 parents 2ed3cb0 + 7282297 commit a5010d5
Show file tree
Hide file tree
Showing 24 changed files with 361 additions and 88 deletions.
30 changes: 18 additions & 12 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
[package]
name = "redstone"
version = "1.0.0"
version = "1.1.0"
edition = "2021"
authors = ["RedStone <https://redstone.finance>"]
description = "A Rust implementation of deserializing&decrypting RedStone payload"

[features]
default = ["core", "network"]
default = ["pure"]

# A core functionality of the package.
core = ["sha3/asm"]
# Pure Rust, no specific network extension
pure = ["primitive-types"]

# An interface for the network to be extended.
network = []
# An extension for Casper network
network_casper = ["casper-contract/wee_alloc", "casper-types"]

# An extension for casper network
network_casper = ["casper-contract/wee_alloc", "casper-types", "network"]
# An extension for Radix network
network_radix = ["radix-common", "scrypto"]

# An extension for debug-printing of messages in the Casper extension. Not supported by Casper Contracts deployed to the network.
print_debug = ["casper-contract/test-support"]
casper_debug = ["print_debug", "casper-contract/test-support"]

# An extension for debug-printing of messages.
print_debug = []

# A variant of decrypting the message-signers using secp256k1 library. Cheaper in runtime.
crypto_secp256k1 = ["secp256k1/recovery", "secp256k1/lowmemory", "secp256k1/alloc"]
Expand All @@ -27,15 +30,18 @@ crypto_secp256k1 = ["secp256k1/recovery", "secp256k1/lowmemory", "secp256k1/allo
crypto_k256 = ["k256/alloc", "k256/sha256", "k256/ecdsa"]

# A set of helpers for testing & offline usage.
helpers = ["hex/serde", "hex/alloc", "network"]
helpers = ["hex/serde", "hex/alloc"]

[dependencies]
casper-contract = { version = "^4.0.0", default-features = false, features = [], optional = true }
casper-types = { version = "^4.0.1", default-features = false, features = [], optional = true }
sha3 = { version = "^0.10.8", default-features = false, features = [], optional = true }
radix-common = { version = "^1.2.0", default-features = false, features = [], optional = true }
scrypto = { version = "^1.2.0", optional = true }
sha3 = { version = "^0.10.8", default-features = false, features = ["asm"] }
k256 = { version = "^0.13.3", default-features = false, features = [], optional = true }
secp256k1 = { version = "^0.29.0", default-features = false, features = [], optional = true }
hex = { version = "^0.4.3", default-features = false, features = [], optional = true }
primitive-types = { version = "^0.13.1", optional = true }

[dev-dependencies]
itertools = { version = "^0.12.1" }
itertools = { version = "^0.13.0" }
3 changes: 1 addition & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
CLIPPY=cargo clippy --release --fix --allow-dirty --allow-staged
DOC=cargo doc --no-deps --document-private-items
TEST=RUST_BACKTRACE=full cargo test --features="helpers"
FEATURE_SETS="crypto_k256" "crypto_k256,network_casper" "crypto_secp256k1" "crypto_secp256k1,network_casper"

FEATURE_SETS="crypto_k256" "crypto_k256,network_casper" "crypto_secp256k1" "crypto_secp256k1,network_casper" "crypto_k256,network_radix" "crypto_secp256k1" "crypto_secp256k1,network_radix"

prepare:
@rustup target add wasm32-unknown-unknown
Expand Down
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,12 @@

## See autogenerated docs for:

1. [`redstone` crate with `crypto_secp256k1` and `network_casper`](https://redstone-docs-git-casper-redstone-finance.vercel.app/rust/casper/redstone/crypto_secp256k1,network_casper/redstone/index.html)
features (the base version for [contracts](../contracts/README.md))
1. [`redstone` crate with
`crypto_secp256k1`](https://docs.redstone.finance/rust/redstone/crypto_secp256k1/redstone/index.html)
pure Rust implementation
2. [`redstone` crate with `crypto_secp256k1` and
`network_casper`](https://docs.redstone.finance/rust/redstone/crypto_secp256k1,network_casper/redstone/index.html)
extension for Casper
3. [`redstone` crate with `crypto_secp256k1` and
`network_radix`](https://docs.redstone.finance/rust/redstone/crypto_secp256k1,network_radix/redstone/index.html)
extension for Radix
1 change: 1 addition & 0 deletions rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
imports_granularity = "Crate"
3 changes: 1 addition & 2 deletions src/crypto/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
pub(crate) mod recover;

mod keccak256;
pub(crate) mod recover;
10 changes: 5 additions & 5 deletions src/crypto/recover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub fn recover_address(message: Vec<u8>, signature: Vec<u8>) -> Vec<u8> {
}

#[cfg(feature = "crypto_secp256k1")]
pub mod crypto256 {
pub(crate) mod crypto256 {
use crate::network::{assert::Unwrap, error::Error};
use secp256k1::{ecdsa::RecoverableSignature, Message, Secp256k1 as Secp256k1Curve};

Expand All @@ -40,11 +40,11 @@ pub mod crypto256 {
}

#[cfg(feature = "crypto_k256")]
pub mod crypto256 {
pub(crate) mod crypto256 {
use crate::network::{assert::Unwrap, error::Error};
use k256::ecdsa::{RecoveryId, Signature, VerifyingKey};

pub fn recover_public_key(
pub(crate) fn recover_public_key(
message_hash: Box<[u8]>,
signature_bytes: &[u8],
recovery_byte: u8,
Expand All @@ -64,8 +64,8 @@ pub mod crypto256 {
}

#[cfg(all(not(feature = "crypto_k256"), not(feature = "crypto_secp256k1")))]
pub mod crypto256 {
pub fn recover_public_key(
pub(crate) mod crypto256 {
pub(crate) fn recover_public_key(
_message_hash: Box<[u8]>,
_signature_bytes: &[u8],
_recovery_byte: u8,
Expand Down
5 changes: 4 additions & 1 deletion src/helpers/hex.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::network::specific::{Bytes, FromBytesRepr, U256};
use crate::network::{
from_bytes_repr::FromBytesRepr,
specific::{Bytes, U256},
};
use hex::{decode, encode};
use std::{fs::File, io::Read};

Expand Down
13 changes: 2 additions & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,16 @@
//! # RedStone
//!
//! `redstone` is a collection of utilities to make deserializing&decrypting RedStone payload.
//! It contains a pure Rust implementation and also an extension for the Casper network.
//! It includes a pure Rust implementation, along with extensions for certain networks.
//!
//! Different crypto-mechanisms are easily injectable.
//! The current implementation contains `secp256k1`- and `k256`-based variants.
#[cfg(feature = "core")]
pub mod core;

#[cfg(feature = "core")]
mod crypto;

#[cfg(feature = "core")]
pub mod network;
mod protocol;

#[cfg(feature = "core")]
mod utils;

#[cfg(feature = "network")]
pub mod network;

#[cfg(feature = "helpers")]
pub mod helpers;
42 changes: 42 additions & 0 deletions src/network/as_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub trait AsHexStr {
}

impl AsHexStr for &[u8] {
#[allow(clippy::format_collect)]
fn as_hex_str(&self) -> String {
self.iter().map(|byte| format!("{:02x}", byte)).collect()
}
Expand All @@ -20,12 +21,27 @@ impl AsHexStr for casper_types::bytesrepr::Bytes {
}
}

#[cfg(not(feature = "network_radix"))]
impl AsHexStr for U256 {
fn as_hex_str(&self) -> String {
format!("{:X}", self)
}
}

#[cfg(feature = "network_radix")]
impl AsHexStr for U256 {
fn as_hex_str(&self) -> String {
let digits = self.to_digits();
let mut result = String::new();
for &part in &digits {
if result.is_empty() || part != 0u64 {
result.push_str(&format!("{:02X}", part));
}
}
result
}
}

impl AsHexStr for Vec<u8> {
fn as_hex_str(&self) -> String {
self.as_slice().as_hex_str()
Expand Down Expand Up @@ -73,3 +89,29 @@ impl AsAsciiStr for U256 {
bytes.as_ascii_str()
}
}

#[cfg(test)]
mod tests {
use crate::network::{
as_str::{AsAsciiStr, AsHexStr},
specific::U256,
};

const ETH: u32 = 4543560u32;

#[test]
fn test_as_hex_str() {
let u256 = U256::from(ETH);
let result = u256.as_hex_str();

assert_eq!(result, "455448");
}

#[test]
fn test_as_ascii_str() {
let u256 = U256::from(ETH);
let result = u256.as_ascii_str();

assert_eq!(result, "ETH");
}
}
7 changes: 5 additions & 2 deletions src/network/casper/from_bytes_repr.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use crate::network::specific::{FromBytesRepr, U256};
use crate::network::{
from_bytes_repr::{FromBytesRepr, Sanitized},
specific::U256,
};

impl FromBytesRepr<Vec<u8>> for U256 {
fn from_bytes_repr(bytes: Vec<u8>) -> Self {
bytes.as_slice().into()
bytes.sanitized().as_slice().into()
}
}
128 changes: 128 additions & 0 deletions src/network/from_bytes_repr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
use crate::network::specific::VALUE_SIZE;

pub trait FromBytesRepr<T> {
fn from_bytes_repr(bytes: T) -> Self;
}

pub trait Sanitized {
fn sanitized(self) -> Self;
}

impl Sanitized for Vec<u8> {
fn sanitized(self) -> Self {
if self.len() <= VALUE_SIZE {
return self;
}

let index = self.len().max(VALUE_SIZE) - VALUE_SIZE;
let remainder = &self[0..index];

if remainder != vec![0; index] {
panic!("Number to big: {:?} digits", self.len())
}

self[index..].into()
}
}

#[cfg(test)]
mod tests {
use crate::network::{
from_bytes_repr::FromBytesRepr,
specific::{U256, VALUE_SIZE},
};

#[cfg(feature = "network_radix")]
use crate::network::radix::u256_ext::U256Ext;

#[test]
fn test_from_bytes_repr_single() {
let vec = vec![1];
let result = U256::from_bytes_repr(vec);

assert_eq!(result, U256::from(1u32));
}

#[test]
fn test_from_bytes_repr_double() {
let vec = vec![1, 2];
let result = U256::from_bytes_repr(vec);

assert_eq!(result, U256::from(258u32));
}

#[test]
fn test_from_bytes_repr_simple() {
let vec = vec![1, 2, 3];
let result = U256::from_bytes_repr(vec);

assert_eq!(result, U256::from(66051u32));
}

#[test]
fn test_from_bytes_repr_bigger() {
let vec = vec![101, 202, 255];
let result = U256::from_bytes_repr(vec);

assert_eq!(result, U256::from(6671103u32));
}

#[test]
fn test_from_bytes_repr_empty() {
let result = U256::from_bytes_repr(Vec::new());

assert_eq!(result, U256::from(0u8));
}

#[test]
fn test_from_bytes_repr_trailing_zeroes() {
let vec = vec![1, 2, 3, 0];
let result = U256::from_bytes_repr(vec);

assert_eq!(result, U256::from(16909056u32));
}

#[test]
fn test_from_bytes_repr_leading_zeroes() {
let vec = vec![0, 1, 2, 3];
let result = U256::from_bytes_repr(vec);

assert_eq!(result, U256::from(66051u32));
}

#[allow(clippy::legacy_numeric_constants)]
#[test]
fn test_from_bytes_repr_max() {
let vec = vec![255; VALUE_SIZE];
let result = U256::from_bytes_repr(vec);

assert_eq!(result, U256::max_value());
}

#[test]
fn test_from_bytes_repr_min() {
let vec = vec![0; VALUE_SIZE];
let result = U256::from_bytes_repr(vec);

assert_eq!(result, U256::from(0u8));
}

#[should_panic(expected = "Number to big")]
#[test]
fn test_from_bytes_repr_too_long() {
let x = VALUE_SIZE as u8 + 1;
let vec = (1..=x).collect();

U256::from_bytes_repr(vec);
}

#[allow(clippy::legacy_numeric_constants)]
#[test]
fn test_from_bytes_repr_too_long_but_zeroes() {
let mut vec = vec![255; VALUE_SIZE + 1];
vec[0] = 0;
let result = U256::from_bytes_repr(vec);

assert_eq!(result, U256::max_value());
}
}
15 changes: 11 additions & 4 deletions src/network/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub mod as_str;
pub mod assert;
pub mod error;
pub mod from_bytes_repr;
pub mod print_debug;
pub mod specific;

Expand All @@ -10,9 +11,15 @@ pub mod casper;
#[cfg(feature = "network_casper")]
pub type _Network = casper::Casper;

#[cfg(feature = "network_radix")]
pub mod radix;

#[cfg(feature = "network_radix")]
pub type _Network = radix::Radix;

pub mod flattened;
#[cfg(not(feature = "network_casper"))]
mod std;
#[cfg(all(not(feature = "network_casper"), not(feature = "network_radix")))]
mod pure;

#[cfg(not(feature = "network_casper"))]
pub type _Network = std::Std;
#[cfg(all(not(feature = "network_casper"), not(feature = "network_radix")))]
pub type _Network = pure::Std;
Loading

0 comments on commit a5010d5

Please sign in to comment.