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    ContractError, ContractId, Event, StandardBufSerializer, ARGBUF_LEN,
11    CONTRACT_ID_BYTES,
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}
50
51#[cfg(feature = "abi")]
52pub(crate) mod host_queries {
53    #[cfg(feature = "abi-debug")]
54    pub use piecrust_uplink::debug as piecrust_debug;
55    pub use piecrust_uplink::{
56        call, call_raw, call_raw_with_limit, call_with_limit, caller,
57        callstack, emit, emit_raw, feed, limit, self_id, spent, wrap_call,
58        wrap_call_unchecked, /* maybe use for our Transaction in
59                              * spend_and_execute */
60    };
61
62    use alloc::vec::Vec;
63
64    use dusk_bytes::Serializable;
65    use piecrust_uplink::{host_query, meta_data};
66
67    use crate::abi::{ContractId, Metadata, Query};
68    use crate::signatures::bls::{
69        MultisigSignature, PublicKey as BlsPublicKey, Signature as BlsSignature,
70    };
71    use crate::signatures::schnorr::{
72        PublicKey as SchnorrPublicKey, Signature as SchnorrSignature,
73    };
74    use crate::BlsScalar;
75
76    /// Compute the blake2b hash of the given bytes, returning the resulting
77    /// scalar. The output of the hasher is truncated (last nibble) to fit
78    /// onto a scalar.
79    #[must_use]
80    pub fn hash(bytes: Vec<u8>) -> BlsScalar {
81        host_query(Query::HASH, bytes)
82    }
83
84    /// Compute the poseidon hash of the given scalars
85    #[must_use]
86    pub fn poseidon_hash(scalars: Vec<BlsScalar>) -> BlsScalar {
87        host_query(Query::POSEIDON_HASH, scalars)
88    }
89
90    /// Verify that a Groth16 proof in the BN254 pairing is valid for a given
91    /// circuit and inputs.
92    ///
93    /// `proof` and `inputs` should be in compressed form, while `pvk`
94    /// uncompressed.
95    #[must_use]
96    pub fn verify_groth16_bn254(
97        pvk: Vec<u8>,
98        proof: Vec<u8>,
99        inputs: Vec<u8>,
100    ) -> bool {
101        host_query(Query::VERIFY_GROTH16_BN254, (pvk, proof, inputs))
102    }
103
104    /// Verify a Plonk proof is valid for a given circuit type and public inputs
105    #[must_use]
106    pub fn verify_plonk(
107        verifier_data: Vec<u8>,
108        proof: Vec<u8>,
109        public_inputs: Vec<BlsScalar>,
110    ) -> bool {
111        host_query(Query::VERIFY_PLONK, (verifier_data, proof, public_inputs))
112    }
113
114    /// Verify a schnorr signature is valid for the given public key and message
115    #[must_use]
116    pub fn verify_schnorr(
117        msg: BlsScalar,
118        pk: SchnorrPublicKey,
119        sig: SchnorrSignature,
120    ) -> bool {
121        host_query(Query::VERIFY_SCHNORR, (msg, pk, sig))
122    }
123
124    /// Verify a BLS signature is valid for the given public key and message
125    #[must_use]
126    pub fn verify_bls(
127        msg: Vec<u8>,
128        pk: BlsPublicKey,
129        sig: BlsSignature,
130    ) -> bool {
131        host_query(Query::VERIFY_BLS, (msg, pk, sig))
132    }
133
134    /// Verify a BLS signature is valid for the given public key and message
135    #[must_use]
136    pub fn verify_bls_multisig(
137        msg: Vec<u8>,
138        keys: Vec<BlsPublicKey>,
139        sig: MultisigSignature,
140    ) -> bool {
141        host_query(Query::VERIFY_BLS_MULTISIG, (msg, keys, sig))
142    }
143
144    /// Compute the keccak256 hash of the given bytes, returning the resulting
145    /// bytes.
146    #[must_use]
147    pub fn keccak256(bytes: Vec<u8>) -> [u8; 32] {
148        host_query(Query::KECCAK256, bytes)
149    }
150
151    /// Get the chain ID.
152    ///
153    /// # Panics
154    /// Panics if the chain doesn't store a `u8` `CHAIN_ID` in the metadata.
155    #[must_use]
156    pub fn chain_id() -> u8 {
157        meta_data(Metadata::CHAIN_ID).unwrap()
158    }
159
160    /// Get the current block height.
161    ///
162    /// # Panics
163    /// Panics if the chain doesn't store a `u64` `BLOCK_HEIGHT` in the
164    /// metadata.
165    #[must_use]
166    pub fn block_height() -> u64 {
167        meta_data(Metadata::BLOCK_HEIGHT).unwrap()
168    }
169
170    /// Get the public sender of the ongoing tx. Returns `None` if the
171    /// transaction is shielded.
172    ///
173    /// # Panics
174    /// Panics if the chain doesn't store a `Option<BlsPublicKey>`
175    /// `PUBLIC_SENDER` in the metadata.
176    #[must_use]
177    pub fn public_sender() -> Option<BlsPublicKey> {
178        meta_data(Metadata::PUBLIC_SENDER)
179            .expect("moonlight sender metadata to be set")
180    }
181
182    /// Query owner of a given contract.
183    /// Returns none if contract is not found.
184    ///
185    /// # Panics
186    /// Panics if owner is not a valid public key (should never happen).
187    #[must_use]
188    pub fn owner(contract: ContractId) -> Option<BlsPublicKey> {
189        owner_raw(contract).map(|buf| {
190            BlsPublicKey::from_bytes(&buf)
191                .expect("Owner should deserialize correctly")
192        })
193    }
194
195    /// Query self owner of a given contract.
196    ///
197    /// # Panics
198    /// Panics if owner is not a valid public key (should never happen).
199    #[must_use]
200    pub fn self_owner() -> BlsPublicKey {
201        let buf = self_owner_raw();
202        BlsPublicKey::from_bytes(&buf)
203            .expect("Owner should deserialize correctly")
204    }
205
206    /// Query raw `to_bytes` serialization of the owner of a given contract.
207    #[must_use]
208    pub fn owner_raw(contract: ContractId) -> Option<[u8; BlsPublicKey::SIZE]> {
209        piecrust_uplink::owner(contract)
210    }
211
212    /// Query raw `to_bytes` serialization of the self owner.
213    #[must_use]
214    pub fn self_owner_raw() -> [u8; BlsPublicKey::SIZE] {
215        piecrust_uplink::self_owner()
216    }
217}