Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 34 additions & 3 deletions soroban-sdk-macros/src/map_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ pub const FP2_SERIALIZED_SIZE: u32 = FP_SERIALIZED_SIZE * 2;
pub const G1_SERIALIZED_SIZE: u32 = FP_SERIALIZED_SIZE * 2;
pub const G2_SERIALIZED_SIZE: u32 = FP2_SERIALIZED_SIZE * 2;

// BN254 constants - values must match soroban_sdk::crypto::bn254
pub const BN254_FP_SERIALIZED_SIZE: u32 = 32;
pub const BN254_G1_SERIALIZED_SIZE: u32 = BN254_FP_SERIALIZED_SIZE * 2; // 64
pub const BN254_G2_SERIALIZED_SIZE: u32 = BN254_G1_SERIALIZED_SIZE * 2; // 128

#[allow(clippy::too_many_lines)]
pub fn map_type(t: &Type, allow_ref: bool, allow_hash: bool) -> Result<ScSpecTypeDef, Error> {
match t {
Expand Down Expand Up @@ -53,13 +58,13 @@ pub fn map_type(t: &Type, allow_ref: bool, allow_hash: bool) -> Result<ScSpecTyp
"MuxedAddress" => Ok(ScSpecTypeDef::MuxedAddress),
"Timepoint" => Ok(ScSpecTypeDef::Timepoint),
"Duration" => Ok(ScSpecTypeDef::Duration),
// The BLS types defined below are represented in the contract's
// The BLS and BN types defined below are represented in the contract's
// interface by their underlying data types, i.e.
// Fp/Fp2/G1Affine/G2Affine => BytesN<N>, Fr => U256. This approach
// simplifies integration with contract development tooling, as it
// avoids introducing new spec types for these BLS constructs.
// avoids introducing new spec types for these constructs.
//
// While this is functionally sound because the BLS types are
// While this is functionally sound because the types are
// essentially newtypes over their inner representations, it means
// that the specific semantic meaning of `G1Affine`, `G2Affine`, or
// `Fr` is not directly visible in the compiled WASM interface. For
Expand All @@ -71,6 +76,9 @@ pub fn map_type(t: &Type, allow_ref: bool, allow_hash: bool) -> Result<ScSpecTyp
// Idiom. For more details, see the tracking issue for supporting
// type aliases:
// https://github.com/stellar/rs-soroban-sdk/issues/1063

// These BLS12-381 unprefixed type names
// will be removed in a future release.
"Fp" => Ok(ScSpecTypeDef::BytesN(ScSpecTypeBytesN {
n: FP_SERIALIZED_SIZE,
})),
Expand All @@ -84,6 +92,29 @@ pub fn map_type(t: &Type, allow_ref: bool, allow_hash: bool) -> Result<ScSpecTyp
n: G2_SERIALIZED_SIZE,
})),
"Fr" => Ok(ScSpecTypeDef::U256),
// BLS12-381 prefixed type names
"Bls12381Fp" => Ok(ScSpecTypeDef::BytesN(ScSpecTypeBytesN {
n: FP_SERIALIZED_SIZE,
})),
"Bls12381Fp2" => Ok(ScSpecTypeDef::BytesN(ScSpecTypeBytesN {
n: FP2_SERIALIZED_SIZE,
})),
"Bls12381G1Affine" => Ok(ScSpecTypeDef::BytesN(ScSpecTypeBytesN {
n: G1_SERIALIZED_SIZE,
})),
"Bls12381G2Affine" => Ok(ScSpecTypeDef::BytesN(ScSpecTypeBytesN {
n: G2_SERIALIZED_SIZE,
})),
// BN254 prefixed type names
"Bn254Fp" => Ok(ScSpecTypeDef::BytesN(ScSpecTypeBytesN {
n: BN254_FP_SERIALIZED_SIZE,
})),
"Bn254G1Affine" => Ok(ScSpecTypeDef::BytesN(ScSpecTypeBytesN {
n: BN254_G1_SERIALIZED_SIZE,
})),
"Bn254G2Affine" => Ok(ScSpecTypeDef::BytesN(ScSpecTypeBytesN {
n: BN254_G2_SERIALIZED_SIZE,
})),
s => Ok(ScSpecTypeDef::Udt(ScSpecTypeUdt {
name: s.try_into().map_err(|e| {
Error::new(
Expand Down
42 changes: 27 additions & 15 deletions soroban-sdk/src/crypto/bls12_381.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub struct Bls12_381 {
env: Env,
}

/// `G1Affine` is a point in the G1 group (subgroup defined over the base field
/// `Bls12381G1Affine` is a point in the G1 group (subgroup defined over the base field
/// `Fq`) of the BLS12-381 elliptic curve
///
/// # Serialization:
Expand All @@ -42,19 +42,22 @@ pub struct Bls12_381 {
///
/// # Example Usage:
/// ```rust
/// use soroban_sdk::{Env, bytesn, crypto::bls12_381::{Bls12_381, G1Affine}};
/// use soroban_sdk::{Env, bytesn, crypto::bls12_381::{Bls12_381, Bls12381G1Affine}};
/// let env = Env::default();
/// let bls12_381 = env.crypto().bls12_381();
/// let zero = G1Affine::from_bytes(bytesn!(&env, 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000));
/// let one = G1Affine::from_bytes(bytesn!(&env, 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1));
/// let zero = Bls12381G1Affine::from_bytes(bytesn!(&env, 0x400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000));
/// let one = Bls12381G1Affine::from_bytes(bytesn!(&env, 0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1));
/// let res = bls12_381.g1_add(&zero, &one);
/// assert_eq!(res, one);
/// ```
#[derive(Clone)]
#[repr(transparent)]
pub struct G1Affine(BytesN<G1_SERIALIZED_SIZE>);
pub struct Bls12381G1Affine(BytesN<G1_SERIALIZED_SIZE>);

/// `G2Affine` is a point in the G2 group (subgroup defined over the quadratic
/// Type alias for `Bls12381G1Affine` for convenience
pub type G1Affine = Bls12381G1Affine;

/// `Bls12381G2Affine` is a point in the G2 group (subgroup defined over the quadratic
/// extension field `Fq2`) of the BLS12-381 elliptic curve
///
/// # Serialization:
Expand All @@ -72,19 +75,25 @@ pub struct G1Affine(BytesN<G1_SERIALIZED_SIZE>);
/// - sort_flag (bit 2): Must always be unset (0).
#[derive(Clone)]
#[repr(transparent)]
pub struct G2Affine(BytesN<G2_SERIALIZED_SIZE>);
pub struct Bls12381G2Affine(BytesN<G2_SERIALIZED_SIZE>);

/// Type alias for `Bls12381G2Affine` for convenience
pub type G2Affine = Bls12381G2Affine;

/// `Fp` represents an element of the base field `Fq` of the BLS12-381 elliptic
/// `Bls12381Fp` represents an element of the base field `Fq` of the BLS12-381 elliptic
/// curve
///
/// # Serialization:
/// - The 48 bytes represent the **big-endian encoding** of an element in the
/// field `Fp`. The value is serialized as a big-endian integer.
#[derive(Clone)]
#[repr(transparent)]
pub struct Fp(BytesN<FP_SERIALIZED_SIZE>);
pub struct Bls12381Fp(BytesN<FP_SERIALIZED_SIZE>);

/// `Fp2` represents an element of the quadratic extension field `Fq2` of the
/// Type alias for `Bls12381Fp` for convenience
pub type Fp = Bls12381Fp;

/// `Bls12381Fp2` represents an element of the quadratic extension field `Fq2` of the
/// BLS12-381 elliptic curve
///
/// # Serialization:
Expand All @@ -94,7 +103,10 @@ pub struct Fp(BytesN<FP_SERIALIZED_SIZE>);
/// and imaginary components).
#[derive(Clone)]
#[repr(transparent)]
pub struct Fp2(BytesN<FP2_SERIALIZED_SIZE>);
pub struct Bls12381Fp2(BytesN<FP2_SERIALIZED_SIZE>);

/// Type alias for `Bls12381Fp2` for convenience
pub type Fp2 = Bls12381Fp2;

/// `Fr` represents an element in the BLS12-381 scalar field, which is a prime
/// field of order `r` (the order of the G1 and G2 groups). The struct is
Expand All @@ -104,10 +116,10 @@ pub struct Fp2(BytesN<FP2_SERIALIZED_SIZE>);
#[repr(transparent)]
pub struct Fr(U256);

impl_bytesn_repr!(G1Affine, G1_SERIALIZED_SIZE);
impl_bytesn_repr!(G2Affine, G2_SERIALIZED_SIZE);
impl_bytesn_repr!(Fp, FP_SERIALIZED_SIZE);
impl_bytesn_repr!(Fp2, FP2_SERIALIZED_SIZE);
impl_bytesn_repr!(Bls12381G1Affine, G1_SERIALIZED_SIZE);
impl_bytesn_repr!(Bls12381G2Affine, G2_SERIALIZED_SIZE);
impl_bytesn_repr!(Bls12381Fp, FP_SERIALIZED_SIZE);
impl_bytesn_repr!(Bls12381Fp2, FP2_SERIALIZED_SIZE);

impl Fp {
pub fn env(&self) -> &Env {
Expand Down
Loading
Loading