Skip to main content

dusk_core/
abi.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//! The Application Binary Interface (ABI) for the Dusk network.
8
9pub use piecrust_uplink::{
10    ARGBUF_LEN, CONTRACT_ID_BYTES, ContractError, ContractId, Event,
11    StandardBufSerializer,
12};
13
14#[cfg(feature = "abi")]
15pub use self::host_queries::*;
16
17/// Enum storing the metadata identifiers.
18pub enum Metadata {}
19
20impl Metadata {
21    /// The chain-id of the network.
22    pub const CHAIN_ID: &'static str = "chain_id";
23    /// The current block-height.
24    pub const BLOCK_HEIGHT: &'static str = "block_height";
25    /// The sender of the transaction, if the transaction is public.
26    pub const PUBLIC_SENDER: &'static str = "public_sender";
27}
28
29/// Enum storing the available host-queries.
30pub enum Query {}
31
32impl Query {
33    /// Host-function name to compute the hash of some input-data.
34    pub const HASH: &'static str = "hash";
35    /// Host-function name to compute the poseidon-hash of some input-data.
36    pub const POSEIDON_HASH: &'static str = "poseidon_hash";
37    /// Host-function name to verify a plonk-proof.
38    pub const VERIFY_PLONK: &'static str = "verify_plonk";
39    /// Host-function name to verify a groth16-bn254 proof.
40    pub const VERIFY_GROTH16_BN254: &'static str = "verify_groth16_bn254";
41    /// Host-function name to verify a schnorr-signature.
42    pub const VERIFY_SCHNORR: &'static str = "verify_schnorr";
43    /// Host-function name to verify a bls-signature.
44    pub const VERIFY_BLS: &'static str = "verify_bls";
45    /// Host-function name to verify a bls-multisig.
46    pub const VERIFY_BLS_MULTISIG: &'static str = "verify_bls_multisig";
47    /// Host-function name to compute the keccak256 hash.
48    pub const KECCAK256: &'static str = "keccak256";
49    /// Host-function name to compute the sha256 hash.
50    pub const SHA256: &'static str = "sha256";
51    /// Host-function name to verify a KZG point-evaluation proof.
52    pub const VERIFY_KZG_PROOF: &'static str = "verify_kzg_proof";
53    /// Host-function name to recover a secp256k1 public key.
54    pub const SECP256K1_RECOVER: &'static str = "secp256k1_recover";
55}
56
57#[cfg(feature = "abi")]
58pub(crate) mod host_queries {
59    #[cfg(feature = "abi-debug")]
60    pub use piecrust_uplink::debug as piecrust_debug;
61    pub use piecrust_uplink::{
62        call, call_raw, call_raw_with_limit, call_with_limit, caller,
63        callstack, emit, emit_raw, feed, limit, self_id, spent, wrap_call,
64        wrap_call_unchecked, /* maybe use for our Transaction in
65                              * spend_and_execute */
66    };
67
68    use alloc::vec::Vec;
69
70    use dusk_bytes::Serializable;
71    use piecrust_uplink::{host_query, meta_data};
72
73    use crate::BlsScalar;
74    use crate::abi::{ContractId, Metadata, Query};
75    use crate::signatures::bls::{
76        MultisigSignature, PublicKey as BlsPublicKey, Signature as BlsSignature,
77    };
78    use crate::signatures::schnorr::{
79        PublicKey as SchnorrPublicKey, Signature as SchnorrSignature,
80    };
81
82    /// Compute the blake2b hash of the given bytes, returning the resulting
83    /// scalar. The output of the hasher is truncated (last nibble) to fit
84    /// onto a scalar.
85    #[must_use]
86    pub fn hash(bytes: Vec<u8>) -> BlsScalar {
87        host_query(Query::HASH, bytes)
88    }
89
90    /// Compute the poseidon hash of the given scalars
91    #[must_use]
92    pub fn poseidon_hash(scalars: Vec<BlsScalar>) -> BlsScalar {
93        host_query(Query::POSEIDON_HASH, scalars)
94    }
95
96    /// Verify that a Groth16 proof in the BN254 pairing is valid for a given
97    /// circuit and inputs.
98    ///
99    /// `proof` and `inputs` should be in compressed form, while `pvk`
100    /// uncompressed.
101    #[must_use]
102    pub fn verify_groth16_bn254(
103        pvk: Vec<u8>,
104        proof: Vec<u8>,
105        inputs: Vec<u8>,
106    ) -> bool {
107        host_query(Query::VERIFY_GROTH16_BN254, (pvk, proof, inputs))
108    }
109
110    /// Verify a Plonk proof is valid for a given circuit type and public inputs
111    #[must_use]
112    pub fn verify_plonk(
113        verifier_data: Vec<u8>,
114        proof: Vec<u8>,
115        public_inputs: Vec<BlsScalar>,
116    ) -> bool {
117        host_query(Query::VERIFY_PLONK, (verifier_data, proof, public_inputs))
118    }
119
120    /// Verify a schnorr signature is valid for the given public key and message
121    #[must_use]
122    pub fn verify_schnorr(
123        msg: BlsScalar,
124        pk: SchnorrPublicKey,
125        sig: SchnorrSignature,
126    ) -> bool {
127        host_query(Query::VERIFY_SCHNORR, (msg, pk, sig))
128    }
129
130    /// Verify a BLS signature is valid for the given public key and message
131    #[must_use]
132    pub fn verify_bls(
133        msg: Vec<u8>,
134        pk: BlsPublicKey,
135        sig: BlsSignature,
136    ) -> bool {
137        host_query(Query::VERIFY_BLS, (msg, pk, sig))
138    }
139
140    /// Verify a BLS signature is valid for the given public key and message
141    #[must_use]
142    pub fn verify_bls_multisig(
143        msg: Vec<u8>,
144        keys: Vec<BlsPublicKey>,
145        sig: MultisigSignature,
146    ) -> bool {
147        host_query(Query::VERIFY_BLS_MULTISIG, (msg, keys, sig))
148    }
149
150    /// Compute the keccak256 hash of the given bytes, returning the resulting
151    /// bytes.
152    #[must_use]
153    pub fn keccak256(bytes: Vec<u8>) -> [u8; 32] {
154        host_query(Query::KECCAK256, bytes)
155    }
156
157    /// Compute the sha256 hash of the given bytes, returning the resulting
158    /// bytes.
159    #[must_use]
160    pub fn sha256(bytes: Vec<u8>) -> [u8; 32] {
161        host_query(Query::SHA256, bytes)
162    }
163
164    /// Verify a KZG point-evaluation proof for a commitment and evaluation.
165    #[must_use]
166    pub fn verify_kzg_proof(
167        commitment: [u8; 48],
168        z: [u8; 32],
169        y: [u8; 32],
170        proof: [u8; 48],
171    ) -> bool {
172        host_query(Query::VERIFY_KZG_PROOF, (commitment, z, y, proof))
173    }
174
175    /// Recover a secp256k1 public key from a 32-byte message hash and
176    /// signature.
177    ///
178    /// Signature is expected as r(32) || s(32) || v(1), with v in {0,1,27,28}.
179    #[must_use]
180    pub fn secp256k1_recover(
181        msg_hash: [u8; 32],
182        sig: [u8; 65],
183    ) -> Option<[u8; 65]> {
184        host_query(Query::SECP256K1_RECOVER, (msg_hash, sig))
185    }
186
187    /// Get the chain ID.
188    ///
189    /// # Panics
190    /// Panics if the chain doesn't store a `u8` `CHAIN_ID` in the metadata.
191    #[must_use]
192    pub fn chain_id() -> u8 {
193        meta_data(Metadata::CHAIN_ID).unwrap()
194    }
195
196    /// Get the current block height.
197    ///
198    /// # Panics
199    /// Panics if the chain doesn't store a `u64` `BLOCK_HEIGHT` in the
200    /// metadata.
201    #[must_use]
202    pub fn block_height() -> u64 {
203        meta_data(Metadata::BLOCK_HEIGHT).unwrap()
204    }
205
206    /// Get the public sender of the ongoing tx. Returns `None` if the
207    /// transaction is shielded.
208    ///
209    /// # Panics
210    /// Panics if the chain doesn't store a `Option<BlsPublicKey>`
211    /// `PUBLIC_SENDER` in the metadata.
212    #[must_use]
213    pub fn public_sender() -> Option<BlsPublicKey> {
214        meta_data(Metadata::PUBLIC_SENDER)
215            .expect("moonlight sender metadata to be set")
216    }
217
218    /// Query owner of a given contract.
219    /// Returns none if contract is not found.
220    ///
221    /// # Panics
222    /// Panics if owner is not a valid public key (should never happen).
223    #[must_use]
224    pub fn owner(contract: ContractId) -> Option<BlsPublicKey> {
225        owner_raw(contract).map(|buf| {
226            BlsPublicKey::from_bytes(&buf)
227                .expect("Owner should deserialize correctly")
228        })
229    }
230
231    /// Query self owner of a given contract.
232    ///
233    /// # Panics
234    /// Panics if owner is not a valid public key (should never happen).
235    #[must_use]
236    pub fn self_owner() -> BlsPublicKey {
237        let buf = self_owner_raw();
238        BlsPublicKey::from_bytes(&buf)
239            .expect("Owner should deserialize correctly")
240    }
241
242    /// Query raw `to_bytes` serialization of the owner of a given contract.
243    #[must_use]
244    pub fn owner_raw(contract: ContractId) -> Option<[u8; BlsPublicKey::SIZE]> {
245        piecrust_uplink::owner(contract)
246    }
247
248    /// Query raw `to_bytes` serialization of the self owner.
249    #[must_use]
250    pub fn self_owner_raw() -> [u8; BlsPublicKey::SIZE] {
251        piecrust_uplink::self_owner()
252    }
253}