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// elliptic curve types
31pub use dusk_bls12_381::BlsScalar;
32pub use dusk_jubjub::{
33    GENERATOR_EXTENDED, GENERATOR_NUMS_EXTENDED, JubJubAffine, JubJubExtended,
34    JubJubScalar,
35};
36
37/// Signatures used in the Dusk protocol.
38pub mod signatures {
39    /// Types for the bls-signature scheme operating on the `bls12_381` curve.
40    pub mod bls {
41        pub use bls12_381_bls::{
42            Error, MultisigPublicKey, MultisigSignature, PublicKey, SecretKey,
43            Signature,
44        };
45
46        /// BLS signature scheme version.
47        #[derive(Debug, Clone, Copy, Eq, PartialEq)]
48        pub enum BlsVersion {
49            /// Insecure v1 (pre-fork historical compatibility).
50            V1,
51            /// Secure v2 using RFC 9380 hash-to-curve.
52            V2,
53        }
54
55        /// Verify a single BLS signature.
56        ///
57        /// # Errors
58        /// Returns an error if the signature is invalid.
59        pub fn verify(
60            pk: &PublicKey,
61            sig: &Signature,
62            msg: &[u8],
63            v: BlsVersion,
64        ) -> Result<(), Error> {
65            match v {
66                BlsVersion::V2 => pk.verify(sig, msg),
67                BlsVersion::V1 => pk.verify_insecure(sig, msg),
68            }
69        }
70
71        /// Verify a BLS multi-signature.
72        ///
73        /// # Errors
74        /// Returns an error if the signature is invalid.
75        pub fn verify_multisig(
76            apk: &MultisigPublicKey,
77            sig: &MultisigSignature,
78            msg: &[u8],
79            v: BlsVersion,
80        ) -> Result<(), Error> {
81            match v {
82                BlsVersion::V2 => apk.verify(sig, msg),
83                BlsVersion::V1 => apk.verify_insecure(sig, msg),
84            }
85        }
86
87        /// Aggregate public keys for multi-signature verification.
88        ///
89        /// # Errors
90        /// Returns an error if the key list is empty.
91        pub fn aggregate(
92            pks: &[PublicKey],
93            v: BlsVersion,
94        ) -> Result<MultisigPublicKey, Error> {
95            match v {
96                BlsVersion::V2 => MultisigPublicKey::aggregate(pks),
97                BlsVersion::V1 => MultisigPublicKey::aggregate_insecure(pks),
98            }
99        }
100
101        /// Sign a message using the multi-signature scheme.
102        #[must_use]
103        pub fn sign_multisig(
104            sk: &SecretKey,
105            pk: &PublicKey,
106            msg: &[u8],
107            v: BlsVersion,
108        ) -> MultisigSignature {
109            match v {
110                BlsVersion::V2 => sk.sign_multisig(pk, msg),
111                BlsVersion::V1 => sk.sign_multisig_insecure(pk, msg),
112            }
113        }
114
115        /// Sign a message using the single-signature scheme.
116        #[must_use]
117        pub fn sign(sk: &SecretKey, msg: &[u8], v: BlsVersion) -> Signature {
118            match v {
119                BlsVersion::V2 => sk.sign(msg),
120                BlsVersion::V1 => sk.sign_insecure(msg),
121            }
122        }
123    }
124
125    /// Types for the schnorr-signature scheme operating on the `jubjub` curve.
126    pub mod schnorr {
127        pub use jubjub_schnorr::{
128            PublicKey, SecretKey, Signature, SignatureDouble,
129        };
130    }
131}
132
133/// Types and traits to create plonk circuits and generate and verify plonk
134/// proofs.
135#[cfg(feature = "plonk")]
136pub mod plonk {
137    pub use dusk_plonk::prelude::{
138        Circuit, Compiler, Composer, Constraint, Error, PlonkVersion, Proof,
139        Prover, PublicParameters, Verifier, Witness, WitnessPoint,
140    };
141}
142
143/// Groth16 circuitry
144#[cfg(feature = "groth16")]
145pub mod groth16 {
146    pub use ark_groth16::{
147        Groth16, PreparedVerifyingKey, Proof, ProvingKey, VerifyingKey,
148        data_structures, generator, prepare_verifying_key, prover, r1cs_to_qap,
149        verifier,
150    };
151    pub use {
152        ark_bn254 as bn254, ark_relations as relations,
153        ark_serialize as serialize,
154    };
155}
156
157#[inline]
158const fn reserved(b: u8) -> abi::ContractId {
159    let mut bytes = [0u8; abi::CONTRACT_ID_BYTES];
160    bytes[0] = b;
161    abi::ContractId::from_bytes(bytes)
162}
163
164use alloc::string::String;
165use alloc::vec::Vec;
166
167use dusk_bytes::{DeserializableSlice, Error as BytesError};
168
169/// Reads vector from a buffer.
170/// Resets buffer to a position after the bytes read.
171///
172/// # Errors
173/// When length or data could not be read.
174fn read_vec(buf: &mut &[u8]) -> Result<Vec<u8>, BytesError> {
175    let len = usize::try_from(u64::from_reader(buf)?)
176        .map_err(|_| BytesError::InvalidData)?;
177    if buf.len() < len {
178        return Err(BytesError::InvalidData);
179    }
180    let bytes = buf[..len].into();
181    *buf = &buf[len..];
182    Ok(bytes)
183}
184
185/// Reads string from a buffer.
186/// Resets buffer to a position after the bytes read.
187///
188/// # Errors
189/// When length or data could not be read.
190fn read_str(buf: &mut &[u8]) -> Result<String, BytesError> {
191    let len = usize::try_from(u64::from_reader(buf)?)
192        .map_err(|_| BytesError::InvalidData)?;
193    if buf.len() < len {
194        return Err(BytesError::InvalidData);
195    }
196    let str = String::from_utf8(buf[..len].into())
197        .map_err(|_| BytesError::InvalidData)?;
198    *buf = &buf[len..];
199    Ok(str)
200}
201
202/// Reads array from a buffer.
203/// Resets buffer to a position after the bytes read.
204///
205/// # Errors
206/// When length or data could not be read.
207fn read_arr<const N: usize>(buf: &mut &[u8]) -> Result<[u8; N], BytesError> {
208    if buf.len() < N {
209        return Err(BytesError::InvalidData);
210    }
211    let mut a = [0u8; N];
212    a.copy_from_slice(&buf[..N]);
213    *buf = &buf[N..];
214    Ok(a)
215}
216
217#[cfg(test)]
218mod tests {
219    // Dev-dependencies only used in integration tests trigger the
220    // unused_crate_dependencies lint, so we re-import them here.
221    use serde_json as _;
222}