Skip to main content

dusk_core/
lib.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4//
5// Copyright (c) DUSK NETWORK. All rights reserved.
6
7//! Types used for interacting with Dusk's transfer and stake contracts.
8
9#![no_std]
10#![deny(missing_docs)]
11#![deny(rustdoc::broken_intra_doc_links)]
12#![deny(clippy::pedantic)]
13#![allow(clippy::module_name_repetitions)]
14#![allow(clippy::used_underscore_binding)]
15#![cfg_attr(not(target_family = "wasm"), deny(unused_crate_dependencies))]
16#![deny(unused_extern_crates)]
17
18extern crate alloc;
19
20pub mod abi;
21
22pub mod stake;
23pub mod transfer;
24
25mod error;
26pub use error::{Error, TxPreconditionError};
27
28mod dusk;
29pub use dusk::{Dusk, LUX, dusk, from_dusk};
30
31use blake2b_simd as _; // Required to satisfy unused_crate_dependencies
32
33// elliptic curve types
34pub use dusk_bls12_381::BlsScalar;
35pub use dusk_jubjub::{
36    GENERATOR_EXTENDED, GENERATOR_NUMS_EXTENDED, JubJubAffine, JubJubExtended,
37    JubJubScalar,
38};
39
40/// Signatures used in the Dusk protocol.
41pub mod signatures {
42    /// Types for the bls-signature scheme operating on the `bls12_381` curve.
43    pub mod bls {
44        pub use bls12_381_bls::{
45            Error, MultisigPublicKey, MultisigSignature, PublicKey, SecretKey,
46            Signature,
47        };
48
49        /// BLS signature scheme version.
50        #[derive(Debug, Clone, Copy, Eq, PartialEq)]
51        pub enum BlsVersion {
52            /// Insecure v1 (pre-fork historical compatibility).
53            V1,
54            /// Secure v2 using RFC 9380 hash-to-curve.
55            V2,
56        }
57
58        /// Verify a single BLS signature.
59        ///
60        /// # Errors
61        /// Returns an error if the signature is invalid.
62        pub fn verify(
63            pk: &PublicKey,
64            sig: &Signature,
65            msg: &[u8],
66            v: BlsVersion,
67        ) -> Result<(), Error> {
68            match v {
69                BlsVersion::V2 => pk.verify(sig, msg),
70                BlsVersion::V1 => pk.verify_insecure(sig, msg),
71            }
72        }
73
74        /// Verify a BLS multi-signature.
75        ///
76        /// # Errors
77        /// Returns an error if the signature is invalid.
78        pub fn verify_multisig(
79            apk: &MultisigPublicKey,
80            sig: &MultisigSignature,
81            msg: &[u8],
82            v: BlsVersion,
83        ) -> Result<(), Error> {
84            match v {
85                BlsVersion::V2 => apk.verify(sig, msg),
86                BlsVersion::V1 => apk.verify_insecure(sig, msg),
87            }
88        }
89
90        /// Aggregate public keys for multi-signature verification.
91        ///
92        /// # Errors
93        /// Returns an error if the key list is empty.
94        pub fn aggregate(
95            pks: &[PublicKey],
96            v: BlsVersion,
97        ) -> Result<MultisigPublicKey, Error> {
98            match v {
99                BlsVersion::V2 => MultisigPublicKey::aggregate(pks),
100                BlsVersion::V1 => MultisigPublicKey::aggregate_insecure(pks),
101            }
102        }
103
104        /// Sign a message using the multi-signature scheme.
105        #[must_use]
106        pub fn sign_multisig(
107            sk: &SecretKey,
108            pk: &PublicKey,
109            msg: &[u8],
110            v: BlsVersion,
111        ) -> MultisigSignature {
112            match v {
113                BlsVersion::V2 => sk.sign_multisig(pk, msg),
114                BlsVersion::V1 => sk.sign_multisig_insecure(pk, msg),
115            }
116        }
117
118        /// Sign a message using the single-signature scheme.
119        #[must_use]
120        pub fn sign(sk: &SecretKey, msg: &[u8], v: BlsVersion) -> Signature {
121            match v {
122                BlsVersion::V2 => sk.sign(msg),
123                BlsVersion::V1 => sk.sign_insecure(msg),
124            }
125        }
126    }
127
128    /// Types for the schnorr-signature scheme operating on the `jubjub` curve.
129    pub mod schnorr {
130        pub use jubjub_schnorr::{
131            PublicKey, SecretKey, Signature, SignatureDouble,
132        };
133    }
134}
135
136/// Types and traits to create plonk circuits and generate and verify plonk
137/// proofs.
138#[cfg(feature = "plonk")]
139pub mod plonk {
140    pub use dusk_plonk::prelude::{
141        Circuit, Compiler, Composer, Constraint, Error, PlonkVersion, Proof,
142        Prover, PublicParameters, Verifier, Witness, WitnessPoint,
143    };
144}
145
146/// Groth16 circuitry
147#[cfg(feature = "groth16")]
148pub mod groth16 {
149    pub use ark_bn254 as bn254;
150    pub use ark_groth16::{
151        Groth16, PreparedVerifyingKey, Proof, ProvingKey, VerifyingKey,
152        data_structures, generator, prepare_verifying_key, prover, r1cs_to_qap,
153        verifier,
154    };
155    pub use ark_relations as relations;
156    pub use ark_serialize as serialize;
157}
158
159#[inline]
160const fn reserved(b: u8) -> abi::ContractId {
161    let mut bytes = [0u8; abi::CONTRACT_ID_BYTES];
162    bytes[0] = b;
163    abi::ContractId::from_bytes(bytes)
164}
165
166use alloc::string::String;
167use alloc::vec::Vec;
168
169use dusk_bytes::{DeserializableSlice, Error as BytesError};
170
171/// Reads vector from a buffer.
172/// Resets buffer to a position after the bytes read.
173///
174/// # Errors
175/// When length or data could not be read.
176fn read_vec(buf: &mut &[u8]) -> Result<Vec<u8>, BytesError> {
177    let len = usize::try_from(u64::from_reader(buf)?)
178        .map_err(|_| BytesError::InvalidData)?;
179    if buf.len() < len {
180        return Err(BytesError::InvalidData);
181    }
182    let bytes = buf[..len].into();
183    *buf = &buf[len..];
184    Ok(bytes)
185}
186
187/// Reads string from a buffer.
188/// Resets buffer to a position after the bytes read.
189///
190/// # Errors
191/// When length or data could not be read.
192fn read_str(buf: &mut &[u8]) -> Result<String, BytesError> {
193    let len = usize::try_from(u64::from_reader(buf)?)
194        .map_err(|_| BytesError::InvalidData)?;
195    if buf.len() < len {
196        return Err(BytesError::InvalidData);
197    }
198    let str = String::from_utf8(buf[..len].into())
199        .map_err(|_| BytesError::InvalidData)?;
200    *buf = &buf[len..];
201    Ok(str)
202}
203
204/// Reads array from a buffer.
205/// Resets buffer to a position after the bytes read.
206///
207/// # Errors
208/// When length or data could not be read.
209fn read_arr<const N: usize>(buf: &mut &[u8]) -> Result<[u8; N], BytesError> {
210    if buf.len() < N {
211        return Err(BytesError::InvalidData);
212    }
213    let mut a = [0u8; N];
214    a.copy_from_slice(&buf[..N]);
215    *buf = &buf[N..];
216    Ok(a)
217}
218
219#[cfg(test)]
220mod tests {
221    // the `unused_crate_dependencies` lint complains for dev-dependencies that
222    // are only used in integration tests, so adding this work-around here
223    use serde_json as _;
224}