diff --git a/contracts/alice/src/lib.rs b/contracts/alice/src/lib.rs index c60f297f87..4720990ba7 100644 --- a/contracts/alice/src/lib.rs +++ b/contracts/alice/src/lib.rs @@ -17,7 +17,7 @@ mod wasm { use super::*; use state::Alice; - use rusk_abi::{ContractId, PaymentInfo}; + use rusk_abi::ContractId; #[no_mangle] static SELF_ID: ContractId = ContractId::uninitialized(); @@ -38,11 +38,4 @@ mod wasm { unsafe fn deposit(arg_len: u32) -> u32 { rusk_abi::wrap_call(arg_len, |arg| STATE.deposit(arg)) } - - const PAYMENT_INFO: PaymentInfo = PaymentInfo::Any(None); - - #[no_mangle] - fn payment_info(arg_len: u32) -> u32 { - rusk_abi::wrap_call(arg_len, |_: ()| PAYMENT_INFO) - } } diff --git a/contracts/bob/src/lib.rs b/contracts/bob/src/lib.rs index b428830f36..c439622bd7 100644 --- a/contracts/bob/src/lib.rs +++ b/contracts/bob/src/lib.rs @@ -17,8 +17,6 @@ use state::Bob; mod wasm { use super::*; - use rusk_abi::PaymentInfo; - #[no_mangle] static mut STATE: Bob = Bob::new(); @@ -41,11 +39,4 @@ mod wasm { unsafe fn value(arg_len: u32) -> u32 { rusk_abi::wrap_call(arg_len, |()| STATE.value()) } - - const PAYMENT_INFO: PaymentInfo = PaymentInfo::Transparent(None); - - #[no_mangle] - fn payment_info(arg_len: u32) -> u32 { - rusk_abi::wrap_call(arg_len, |_: ()| PAYMENT_INFO) - } } diff --git a/contracts/host_fn/src/lib.rs b/contracts/host_fn/src/lib.rs index b178d1fa8a..2e8feeb690 100644 --- a/contracts/host_fn/src/lib.rs +++ b/contracts/host_fn/src/lib.rs @@ -16,7 +16,7 @@ use execution_core::{ BlsPublicKey, BlsScalar, BlsSignature, PublicKey, SchnorrPublicKey, SchnorrSignature, }; -use rusk_abi::{ContractId, PaymentInfo, PublicInput}; +use rusk_abi::ContractId; #[no_mangle] static SELF_ID: ContractId = ContractId::uninitialized(); @@ -39,7 +39,7 @@ impl HostFnTest { &self, verifier_data: Vec, proof: Vec, - public_inputs: Vec, + public_inputs: Vec, ) -> bool { rusk_abi::verify_proof(verifier_data, proof, public_inputs) } @@ -120,10 +120,3 @@ unsafe fn contract_owner(arg_len: u32) -> u32 { unsafe fn contract_owner_raw(arg_len: u32) -> u32 { rusk_abi::wrap_call(arg_len, |_: ()| STATE.owner_raw()) } - -const PAYMENT_INFO: PaymentInfo = PaymentInfo::Transparent(None); - -#[no_mangle] -fn payment_info(arg_len: u32) -> u32 { - rusk_abi::wrap_call(arg_len, |_: ()| PAYMENT_INFO) -} diff --git a/contracts/license/src/state.rs b/contracts/license/src/state.rs index 1d20ab5313..73586d9a9c 100644 --- a/contracts/license/src/state.rs +++ b/contracts/license/src/state.rs @@ -12,7 +12,6 @@ use dusk_bytes::Serializable; use poseidon_merkle::{Opening, Tree}; use execution_core::BlsScalar; -use rusk_abi::PublicInput; use crate::collection::Map; use crate::error::Error; @@ -104,13 +103,12 @@ impl LicenseContractState { /// creates a session with the corresponding session id. /// Method intended to be called by the user. pub fn use_license(&mut self, use_license_arg: UseLicenseArg) { - let mut pi = Vec::new(); - for scalar in use_license_arg.public_inputs.iter() { - pi.push(PublicInput::BlsScalar(*scalar)); - } - let vd = verifier_data_license_circuit(); - Self::assert_proof(vd, use_license_arg.proof.to_bytes().to_vec(), pi) - .expect("Provided proof verification should succeed!"); + Self::assert_proof( + verifier_data_license_circuit(), + use_license_arg.proof.to_bytes().to_vec(), + use_license_arg.public_inputs.clone(), + ) + .expect("Provided proof verification should succeed!"); // after a successful proof verification we can add a session to a // shared list of sessions @@ -139,7 +137,7 @@ impl LicenseContractState { fn assert_proof( verifier_data: &[u8], proof: Vec, - public_inputs: Vec, + public_inputs: Vec, ) -> Result<(), Error> { rusk_abi::verify_proof(verifier_data.to_vec(), proof, public_inputs) .then_some(()) diff --git a/contracts/stake/benches/get_provisioners.rs b/contracts/stake/benches/get_provisioners.rs index aae8881f24..ec75f2d4fc 100644 --- a/contracts/stake/benches/get_provisioners.rs +++ b/contracts/stake/benches/get_provisioners.rs @@ -9,7 +9,7 @@ use execution_core::{stake::StakeData, BlsPublicKey, BlsSecretKey}; use rand::rngs::StdRng; use rand::{CryptoRng, RngCore, SeedableRng}; use rusk_abi::{ - ContractData, Error, Session, STAKE_CONTRACT, TRANSFER_CONTRACT, VM, + ContractData, PiecrustError, Session, STAKE_CONTRACT, TRANSFER_CONTRACT, VM, }; use std::sync::mpsc; @@ -24,7 +24,7 @@ fn config() -> Criterion { Criterion::default().sample_size(SAMPLE_SIZE) } -fn update_root(session: &mut Session) -> Result<(), Error> { +fn update_root(session: &mut Session) -> Result<(), PiecrustError> { session .call(TRANSFER_CONTRACT, "update_root", &(), POINT_LIMIT) .map(|r| r.data) @@ -66,7 +66,7 @@ fn instantiate(vm: &VM) -> Session { fn do_get_provisioners( session: &mut Session, -) -> Result, Error> { +) -> Result, PiecrustError> { let (sender, receiver) = mpsc::channel(); session.feeder_call::<_, ()>( STAKE_CONTRACT, @@ -84,7 +84,7 @@ fn do_get_provisioners( fn do_insert_stake( rng: &mut Rng, session: &mut Session, -) -> Result<(), Error> { +) -> Result<(), PiecrustError> { let stake_data = StakeData { amount: Some((TEST_STAKE, 0)), nonce: 1, diff --git a/contracts/stake/src/lib.rs b/contracts/stake/src/lib.rs index 10405844c8..efe5e7cab1 100644 --- a/contracts/stake/src/lib.rs +++ b/contracts/stake/src/lib.rs @@ -18,7 +18,7 @@ use state::StakeState; /// The minimum amount of Dusk one can stake. pub const MINIMUM_STAKE: Dusk = dusk(1_000.0); -use rusk_abi::{ContractId, PaymentInfo}; +use rusk_abi::ContractId; #[no_mangle] static SELF_ID: ContractId = ContractId::uninitialized(); @@ -150,10 +150,3 @@ fn assert_external_caller() { panic!("Can only be called from the outside the VM"); } } - -const PAYMENT_INFO: PaymentInfo = PaymentInfo::Transparent(None); - -#[no_mangle] -fn payment_info(arg_len: u32) -> u32 { - rusk_abi::wrap_call(arg_len, |_: ()| PAYMENT_INFO) -} diff --git a/contracts/stake/tests/common/utils.rs b/contracts/stake/tests/common/utils.rs index de8b8b7887..875e5e89c5 100644 --- a/contracts/stake/tests/common/utils.rs +++ b/contracts/stake/tests/common/utils.rs @@ -22,14 +22,16 @@ use execution_core::{ value_commitment, JubJubScalar, Note, PublicKey, SchnorrSecretKey, SecretKey, Sender, TxSkeleton, ViewKey, }; -use rusk_abi::{CallReceipt, ContractError, Error, Session, TRANSFER_CONTRACT}; +use rusk_abi::{ + CallReceipt, ContractError, PiecrustError, Session, TRANSFER_CONTRACT, +}; const POINT_LIMIT: u64 = 0x100000000; pub fn leaves_from_height( session: &mut Session, height: u64, -) -> Result, Error> { +) -> Result, PiecrustError> { let (feeder, receiver) = mpsc::channel(); session.feeder_call::<_, ()>( @@ -49,7 +51,7 @@ pub fn leaves_from_height( pub fn leaves_from_pos( session: &mut Session, pos: u64, -) -> Result, Error> { +) -> Result, PiecrustError> { let (feeder, receiver) = mpsc::channel(); session.feeder_call::<_, ()>( @@ -66,13 +68,13 @@ pub fn leaves_from_pos( .collect()) } -pub fn update_root(session: &mut Session) -> Result<(), Error> { +pub fn update_root(session: &mut Session) -> Result<(), PiecrustError> { session .call(TRANSFER_CONTRACT, "update_root", &(), POINT_LIMIT) .map(|r| r.data) } -pub fn root(session: &mut Session) -> Result { +pub fn root(session: &mut Session) -> Result { session .call(TRANSFER_CONTRACT, "root", &(), POINT_LIMIT) .map(|r| r.data) @@ -81,7 +83,7 @@ pub fn root(session: &mut Session) -> Result { pub fn opening( session: &mut Session, pos: u64, -) -> Result>, Error> { +) -> Result>, PiecrustError> { session .call(TRANSFER_CONTRACT, "opening", &pos, POINT_LIMIT) .map(|r| r.data) @@ -123,7 +125,7 @@ pub fn filter_notes_owned_by>( pub fn execute( session: &mut Session, tx: impl Into, -) -> Result, ContractError>>, Error> { +) -> Result, ContractError>>, PiecrustError> { let tx = tx.into(); // Spend the inputs and execute the call. If this errors the transaction is diff --git a/contracts/stake/tests/events.rs b/contracts/stake/tests/events.rs index 1fad7ab226..754baaab0f 100644 --- a/contracts/stake/tests/events.rs +++ b/contracts/stake/tests/events.rs @@ -14,7 +14,7 @@ use execution_core::{ BlsPublicKey, BlsSecretKey, PublicKey, SecretKey, }; use rusk_abi::dusk::dusk; -use rusk_abi::{Error, STAKE_CONTRACT, TRANSFER_CONTRACT}; +use rusk_abi::{PiecrustError, STAKE_CONTRACT, TRANSFER_CONTRACT}; use crate::common::assert::assert_event; use crate::common::init::instantiate; @@ -22,7 +22,7 @@ use crate::common::init::instantiate; const GENESIS_VALUE: u64 = dusk(1_000_000.0); #[test] -fn reward_slash() -> Result<(), Error> { +fn reward_slash() -> Result<(), PiecrustError> { let rng = &mut StdRng::seed_from_u64(0xfeeb); let vm = &mut rusk_abi::new_ephemeral_vm() @@ -111,7 +111,7 @@ fn reward_slash() -> Result<(), Error> { } #[test] -fn stake_hard_slash() -> Result<(), Error> { +fn stake_hard_slash() -> Result<(), PiecrustError> { let rng = &mut StdRng::seed_from_u64(0xfeeb); let vm = &mut rusk_abi::new_ephemeral_vm() diff --git a/contracts/transfer/src/state.rs b/contracts/transfer/src/state.rs index 0a848a8b2f..874f2bd1c3 100644 --- a/contracts/transfer/src/state.rs +++ b/contracts/transfer/src/state.rs @@ -15,7 +15,7 @@ use alloc::vec::Vec; use dusk_bytes::Serializable; use poseidon_merkle::Opening as PoseidonOpening; use ringbuffer::{ConstGenericRingBuffer, RingBuffer}; -use rusk_abi::{ContractError, ContractId, PublicInput, STAKE_CONTRACT}; +use rusk_abi::{ContractError, ContractId, STAKE_CONTRACT}; use execution_core::{ transfer::{ @@ -627,9 +627,6 @@ impl TransferState { } fn verify_tx_proof(tx: &PhoenixTransaction) -> bool { - let pis: Vec = - tx.public_inputs().iter().map(|pi| pi.into()).collect(); - // fetch the verifier data let num_inputs = tx.payload().tx_skeleton.nullifiers.len(); let vd = verifier_data_execute(num_inputs) @@ -637,7 +634,7 @@ fn verify_tx_proof(tx: &PhoenixTransaction) -> bool { .to_vec(); // verify the proof - rusk_abi::verify_proof(vd, tx.proof().to_vec(), pis) + rusk_abi::verify_proof(vd, tx.proof().to_vec(), tx.public_inputs()) } #[cfg(test)] diff --git a/contracts/transfer/tests/common.rs b/contracts/transfer/tests/common.rs index b5c8aad7e7..a18543dcb9 100644 --- a/contracts/transfer/tests/common.rs +++ b/contracts/transfer/tests/common.rs @@ -15,7 +15,9 @@ use execution_core::{ value_commitment, BlsPublicKey, BlsScalar, BlsSecretKey, JubJubScalar, Note, PublicKey, SchnorrSecretKey, SecretKey, Sender, TxSkeleton, ViewKey, }; -use rusk_abi::{ContractError, ContractId, Error, Session, TRANSFER_CONTRACT}; +use rusk_abi::{ + ContractError, ContractId, PiecrustError, Session, TRANSFER_CONTRACT, +}; use dusk_bytes::Serializable; use dusk_plonk::prelude::*; @@ -31,7 +33,7 @@ const GAS_LIMIT: u64 = 0x10_000_000; pub fn leaves_from_height( session: &mut Session, height: u64, -) -> Result, Error> { +) -> Result, PiecrustError> { let (feeder, receiver) = mpsc::channel(); session.feeder_call::<_, ()>( @@ -51,7 +53,7 @@ pub fn leaves_from_height( pub fn leaves_from_pos( session: &mut Session, pos: u64, -) -> Result, Error> { +) -> Result, PiecrustError> { let (feeder, receiver) = mpsc::channel(); session.feeder_call::<_, ()>( @@ -68,19 +70,19 @@ pub fn leaves_from_pos( .collect()) } -pub fn num_notes(session: &mut Session) -> Result { +pub fn num_notes(session: &mut Session) -> Result { session .call(TRANSFER_CONTRACT, "num_notes", &(), u64::MAX) .map(|r| r.data) } -pub fn update_root(session: &mut Session) -> Result<(), Error> { +pub fn update_root(session: &mut Session) -> Result<(), PiecrustError> { session .call(TRANSFER_CONTRACT, "update_root", &(), GAS_LIMIT) .map(|r| r.data) } -pub fn root(session: &mut Session) -> Result { +pub fn root(session: &mut Session) -> Result { session .call(TRANSFER_CONTRACT, "root", &(), GAS_LIMIT) .map(|r| r.data) @@ -89,7 +91,7 @@ pub fn root(session: &mut Session) -> Result { pub fn account( session: &mut Session, pk: &BlsPublicKey, -) -> Result { +) -> Result { session .call(TRANSFER_CONTRACT, "account", pk, GAS_LIMIT) .map(|r| r.data) @@ -98,7 +100,7 @@ pub fn account( pub fn contract_balance( session: &mut Session, contract: ContractId, -) -> Result { +) -> Result { session .call(TRANSFER_CONTRACT, "contract_balance", &contract, GAS_LIMIT) .map(|r| r.data) @@ -107,7 +109,7 @@ pub fn contract_balance( pub fn opening( session: &mut Session, pos: u64, -) -> Result>, Error> { +) -> Result>, PiecrustError> { session .call(TRANSFER_CONTRACT, "opening", &pos, GAS_LIMIT) .map(|r| r.data) @@ -141,7 +143,7 @@ pub fn prover_verifier(input_notes: usize) -> (Prover, Verifier) { pub fn execute( session: &mut Session, tx: impl Into, -) -> Result { +) -> Result { let tx = tx.into(); let mut receipt = session.call::<_, Result, ContractError>>( diff --git a/execution-core/src/transfer/transaction.rs b/execution-core/src/transfer/transaction.rs index a0cf142285..07f51aeb85 100644 --- a/execution-core/src/transfer/transaction.rs +++ b/execution-core/src/transfer/transaction.rs @@ -234,6 +234,15 @@ impl Transaction { Self::Moonlight(tx) => tx.to_hash_input_bytes(), } } + + /// Create the unique transaction hash. + #[must_use] + pub fn hash(&self) -> BlsScalar { + match self { + Self::Phoenix(tx) => tx.hash(), + Self::Moonlight(tx) => tx.hash(), + } + } } impl From for Transaction { diff --git a/node-data/src/ledger.rs b/node-data/src/ledger.rs index b314a245a3..2ee32fadda 100644 --- a/node-data/src/ledger.rs +++ b/node-data/src/ledger.rs @@ -24,7 +24,6 @@ pub use attestation::{ use crate::bls::PublicKeyBytes; use crate::Serializable; -use rusk_abi::hash::Hasher; use sha3::Digest; use std::io::{self, Read, Write}; diff --git a/node-data/src/ledger/faults.rs b/node-data/src/ledger/faults.rs index 8409967d83..36e03b096d 100644 --- a/node-data/src/ledger/faults.rs +++ b/node-data/src/ledger/faults.rs @@ -16,7 +16,7 @@ use crate::{ use dusk_bytes::Serializable as DuskSerializeble; use execution_core::{ - stake::EPOCH, BlsAggPublicKey, BlsSigError, BlsSignature, + stake::EPOCH, BlsAggPublicKey, BlsScalar, BlsSigError, BlsSignature, }; use thiserror::Error; use tracing::error; @@ -62,7 +62,7 @@ impl Fault { pub fn hash(&self) -> [u8; 32] { let mut b = vec![]; self.write(&mut b).expect("Write to a vec shall not fail"); - Hasher::digest(b).to_bytes() + BlsScalar::hash_to_scalar(&b[..]).to_bytes() } pub fn same(&self, other: &Fault) -> bool { @@ -80,20 +80,26 @@ impl Fault { match self { Fault::DoubleCandidate(a, b) => { let seed = Candidate::SIGN_SEED; - let a = Hasher::digest(a.get_signed_data(seed)).to_bytes(); - let b = Hasher::digest(b.get_signed_data(seed)).to_bytes(); + let a = BlsScalar::hash_to_scalar(&a.get_signed_data(seed)[..]) + .to_bytes(); + let b = BlsScalar::hash_to_scalar(&b.get_signed_data(seed)[..]) + .to_bytes(); (a, b) } Fault::DoubleRatificationVote(a, b) => { let seed = Ratification::SIGN_SEED; - let a = Hasher::digest(a.get_signed_data(seed)).to_bytes(); - let b = Hasher::digest(b.get_signed_data(seed)).to_bytes(); + let a = BlsScalar::hash_to_scalar(&a.get_signed_data(seed)[..]) + .to_bytes(); + let b = BlsScalar::hash_to_scalar(&b.get_signed_data(seed)[..]) + .to_bytes(); (a, b) } Fault::DoubleValidationVote(a, b) => { let seed = Validation::SIGN_SEED; - let a = Hasher::digest(a.get_signed_data(seed)).to_bytes(); - let b = Hasher::digest(b.get_signed_data(seed)).to_bytes(); + let a = BlsScalar::hash_to_scalar(&a.get_signed_data(seed)[..]) + .to_bytes(); + let b = BlsScalar::hash_to_scalar(&b.get_signed_data(seed)[..]) + .to_bytes(); (a, b) } } diff --git a/node-data/src/ledger/transaction.rs b/node-data/src/ledger/transaction.rs index e291b243e1..3315754316 100644 --- a/node-data/src/ledger/transaction.rs +++ b/node-data/src/ledger/transaction.rs @@ -4,9 +4,8 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. -use super::*; - use execution_core::transfer::Transaction as ProtocolTransaction; +use execution_core::BlsScalar; #[derive(Debug, Clone)] pub struct Transaction { @@ -42,7 +41,7 @@ impl Transaction { /// ### Returns /// An array of 32 bytes representing the hash of the transaction. pub fn hash(&self) -> [u8; 32] { - Hasher::digest(self.inner.to_var_bytes()).to_bytes() + BlsScalar::hash_to_scalar(&self.inner.to_var_bytes()[..]).to_bytes() } /// Computes the transaction ID. @@ -56,7 +55,7 @@ impl Transaction { /// ### Returns /// An array of 32 bytes representing the transaction ID. pub fn id(&self) -> [u8; 32] { - Hasher::digest(self.inner.to_hash_input_bytes()).to_bytes() + self.inner.hash().to_bytes() } pub fn gas_price(&self) -> u64 { @@ -93,6 +92,7 @@ impl Eq for SpentTransaction {} #[cfg(any(feature = "faker", test))] pub mod faker { use super::*; + use crate::ledger::Dummy; use execution_core::transfer::{ ContractCall, ContractExec, Fee, PhoenixPayload, }; diff --git a/rusk-abi/src/abi.rs b/rusk-abi/src/abi.rs index 870220eb2c..4afde9a2b5 100644 --- a/rusk-abi/src/abi.rs +++ b/rusk-abi/src/abi.rs @@ -4,83 +4,59 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. -#[cfg(feature = "abi")] +use alloc::vec::Vec; + use dusk_bytes::Serializable; -#[cfg(feature = "abi")] use execution_core::{ BlsPublicKey, BlsScalar, BlsSignature, PublicKey, SchnorrPublicKey, SchnorrSignature, }; +use piecrust_uplink::{host_query, meta_data}; -pub use piecrust_uplink::*; +use crate::{ContractId, Metadata, Query}; /// Compute the blake2b hash of the given bytes, returning the resulting scalar. /// The output of the hasher is truncated (last nibble) to fit onto a scalar. -#[cfg(feature = "abi")] -pub fn hash(bytes: alloc::vec::Vec) -> BlsScalar { - use crate::Query; +pub fn hash(bytes: Vec) -> BlsScalar { host_query(Query::HASH, bytes) } /// Compute the poseidon hash of the given scalars -#[cfg(feature = "abi")] -pub fn poseidon_hash(scalars: alloc::vec::Vec) -> BlsScalar { - use crate::Query; +pub fn poseidon_hash(scalars: Vec) -> BlsScalar { host_query(Query::POSEIDON_HASH, scalars) } /// Verify a proof is valid for a given circuit type and public inputs -#[cfg(feature = "abi")] pub fn verify_proof( - verifier_data: alloc::vec::Vec, - proof: alloc::vec::Vec, - public_inputs: alloc::vec::Vec, + verifier_data: Vec, + proof: Vec, + public_inputs: Vec, ) -> bool { - use crate::Query; host_query(Query::VERIFY_PROOF, (verifier_data, proof, public_inputs)) } /// Verify a schnorr signature is valid for the given public key and message -#[cfg(feature = "abi")] pub fn verify_schnorr( msg: BlsScalar, pk: SchnorrPublicKey, sig: SchnorrSignature, ) -> bool { - use crate::Query; host_query(Query::VERIFY_SCHNORR, (msg, pk, sig)) } /// Verify a BLS signature is valid for the given public key and message -#[cfg(feature = "abi")] -pub fn verify_bls( - msg: alloc::vec::Vec, - pk: BlsPublicKey, - sig: BlsSignature, -) -> bool { - use crate::Query; +pub fn verify_bls(msg: Vec, pk: BlsPublicKey, sig: BlsSignature) -> bool { host_query(Query::VERIFY_BLS, (msg, pk, sig)) } /// Get the current block height. -#[cfg(feature = "abi")] pub fn block_height() -> u64 { - use crate::Metadata; meta_data(Metadata::BLOCK_HEIGHT).unwrap() } -/// Query a contract for the types of payment it accepts. -#[cfg(feature = "abi")] -pub fn payment_info( - contract: ContractId, -) -> Result { - call(contract, "payment_info", &()) -} - /// Query owner of a given contract. /// Returns none if contract is not found. /// Panics if owner is not a valid public key (should never happen). -#[cfg(feature = "abi")] pub fn owner(contract: ContractId) -> Option { owner_raw(contract).map(|buf| { PublicKey::from_bytes(&buf).expect("Owner should deserialize correctly") @@ -89,20 +65,17 @@ pub fn owner(contract: ContractId) -> Option { /// Query self owner of a given contract. /// Panics if owner is not a valid public key (should never happen). -#[cfg(feature = "abi")] pub fn self_owner() -> PublicKey { let buf = self_owner_raw(); PublicKey::from_bytes(&buf).expect("Owner should deserialize correctly") } /// Query raw "to_bytes" serialization of the owner of a given contract. -#[cfg(feature = "abi")] pub fn owner_raw(contract: ContractId) -> Option<[u8; PublicKey::SIZE]> { piecrust_uplink::owner(contract) } /// Query raw "to_bytes" serialization of the self owner. -#[cfg(feature = "abi")] pub fn self_owner_raw() -> [u8; PublicKey::SIZE] { piecrust_uplink::self_owner() } diff --git a/rusk-abi/src/hash.rs b/rusk-abi/src/hash.rs deleted file mode 100644 index 6bb95e7e83..0000000000 --- a/rusk-abi/src/hash.rs +++ /dev/null @@ -1,79 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -// -// Copyright (c) DUSK NETWORK. All rights reserved. - -use blake2b_simd::{Params, State}; -use execution_core::BlsScalar; - -/// Hashes scalars and arbitrary slices of bytes using Blake2b, returning a -/// valid [`BlsScalar`]. Using the `Hasher` yields the same result as when using -/// `BlsScalar::hash_to_scalar`. -/// -/// This hash cannot be proven inside a circuit, if that is desired, use -/// `poseidon_hash` instead. -pub struct Hasher { - state: State, -} - -impl Default for Hasher { - fn default() -> Self { - Hasher { - state: Params::new().hash_length(64).to_state(), - } - } -} - -impl Hasher { - /// Create new hasher instance. - pub fn new() -> Self { - Self::default() - } - - /// Process data, updating the internal state. - pub fn update(&mut self, data: impl AsRef<[u8]>) { - self.state.update(data.as_ref()); - } - - /// Process input data in a chained manner. - pub fn chain_update(self, data: impl AsRef<[u8]>) -> Self { - let mut hasher = self; - hasher.state.update(data.as_ref()); - hasher - } - - /// Retrieve result and consume hasher instance. - pub fn finalize(self) -> BlsScalar { - BlsScalar::from_bytes_wide(self.state.finalize().as_array()) - } - - /// Compute hash of arbitrary data into a valid [`BlsScalar`]. This - /// equivalent to using `BlsScalar::hash_to_scalar`. - pub fn digest(data: impl AsRef<[u8]>) -> BlsScalar { - let mut hasher = Hasher::new(); - hasher.update(data.as_ref()); - hasher.finalize() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use rand_core::{OsRng, RngCore}; - - #[test] - fn test_hash() { - let mut input = [0u8; 100000]; - OsRng.fill_bytes(&mut input[..]); - - let mut hasher = Hasher::new(); - for input_chunk in input.chunks(100) { - hasher.update(input_chunk); - } - let hash = hasher.finalize(); - - assert_eq!(hash, BlsScalar::hash_to_scalar(&input)); - assert_eq!(hash, Hasher::digest(&input)); - } -} diff --git a/rusk-abi/src/host.rs b/rusk-abi/src/host.rs index 5b3c651330..a0830fbf1c 100644 --- a/rusk-abi/src/host.rs +++ b/rusk-abi/src/host.rs @@ -14,15 +14,13 @@ use execution_core::{ BlsAggPublicKey, BlsPublicKey, BlsScalar, BlsSignature, SchnorrPublicKey, SchnorrSignature, }; +use piecrust::{Error as PiecrustError, Session, SessionData, VM}; use rkyv::ser::serializers::AllocSerializer; use rkyv::{Archive, Deserialize, Serialize}; mod cache; -pub use piecrust::*; - -use crate::hash::Hasher; -use crate::{Metadata, PublicInput, Query}; +use crate::{Metadata, Query}; /// Create a new session based on the given `vm`. The vm *must* have been /// created using [`new_vm`] or [`new_ephemeral_vm`]. @@ -30,7 +28,7 @@ pub fn new_session( vm: &VM, base: [u8; 32], block_height: u64, -) -> Result { +) -> Result { vm.session( SessionData::builder() .base(base) @@ -52,14 +50,14 @@ pub fn new_genesis_session(vm: &VM) -> Session { /// Create a new [`VM`] compliant with Dusk's specification. pub fn new_vm + Into>( root_dir: P, -) -> Result { +) -> Result { let mut vm = VM::new(root_dir)?; register_host_queries(&mut vm); Ok(vm) } /// Creates a new [`VM`] with a temporary directory. -pub fn new_ephemeral_vm() -> Result { +pub fn new_ephemeral_vm() -> Result { let mut vm = VM::ephemeral()?; register_host_queries(&mut vm); Ok(vm) @@ -129,10 +127,10 @@ fn host_verify_bls(arg_buf: &mut [u8], arg_len: u32) -> u32 { } /// Compute the blake2b hash of the given scalars, returning the resulting -/// scalar. The output of the hasher is truncated (last nibble) to fit onto a -/// scalar. +/// scalar. The hash is computed in such a way that it will always return a +/// valid scalar. pub fn hash(bytes: Vec) -> BlsScalar { - Hasher::digest(bytes) + BlsScalar::hash_to_scalar(&bytes[..]) } /// Compute the poseidon hash of the given scalars @@ -147,32 +145,13 @@ pub fn poseidon_hash(scalars: Vec) -> BlsScalar { pub fn verify_proof( verifier_data: Vec, proof: Vec, - public_inputs: Vec, + public_inputs: Vec, ) -> bool { let verifier = Verifier::try_from_bytes(verifier_data) .expect("Verifier data coming from the contract should be valid"); let proof = Proof::from_slice(&proof).expect("Proof should be valid"); - let n_pi = public_inputs.iter().fold(0, |num, pi| { - num + match pi { - PublicInput::Point(_) => 2, - PublicInput::BlsScalar(_) => 1, - PublicInput::JubJubScalar(_) => 1, - } - }); - - let mut pis = Vec::with_capacity(n_pi); - - public_inputs.into_iter().for_each(|pi| match pi { - PublicInput::Point(p) => pis.extend([p.get_u(), p.get_v()]), - PublicInput::BlsScalar(s) => pis.push(s), - PublicInput::JubJubScalar(s) => { - let s: BlsScalar = s.into(); - pis.push(s) - } - }); - - verifier.verify(&proof, &pis[..]).is_ok() + verifier.verify(&proof, &public_inputs[..]).is_ok() } /// Verify a schnorr signature is valid for the given public key and message diff --git a/rusk-abi/src/lib.rs b/rusk-abi/src/lib.rs index 986c186e6c..67753a4523 100644 --- a/rusk-abi/src/lib.rs +++ b/rusk-abi/src/lib.rs @@ -22,29 +22,55 @@ compile_error!("features \"host\" and \"abi\" are mutually exclusive"); extern crate alloc; -mod types; -pub use types::*; +pub use piecrust_uplink::{ + ContractError, ContractId, Event, StandardBufSerializer, ARGBUF_LEN, + CONTRACT_ID_BYTES, +}; +#[cfg(feature = "debug")] +pub use piecrust_uplink::debug as piecrust_debug; + +#[cfg(feature = "abi")] mod abi; -pub use abi::*; +#[cfg(feature = "abi")] +pub use abi::{ + block_height, hash, owner, owner_raw, poseidon_hash, self_owner, + self_owner_raw, verify_bls, verify_proof, verify_schnorr, +}; +#[cfg(feature = "abi")] +pub use piecrust_uplink::{ + call, + call_raw, + call_raw_with_limit, + call_with_limit, + caller, + emit, + feed, + limit, + self_id, + spent, + wrap_call, + wrap_call_unchecked, // maybe use for our Transaction in spend_and_execute +}; #[cfg(feature = "host")] mod host; #[cfg(feature = "host")] -pub use host::*; +pub use host::{ + hash, new_ephemeral_vm, new_genesis_session, new_session, new_vm, + poseidon_hash, verify_bls, verify_proof, verify_schnorr, +}; +#[cfg(feature = "host")] +pub use piecrust::{ + CallReceipt, CallTree, CallTreeElem, ContractData, Error as PiecrustError, + PageOpening, Session, VM, +}; pub mod dusk; -#[doc(hidden)] -pub mod hash; - -use hash::Hasher; use dusk_bytes::DeserializableSlice; use execution_core::BlsScalar; -/// Constant depth of the merkle tree that provides the opening proofs. -pub const POSEIDON_TREE_DEPTH: usize = 17; - /// Label used for the ZK transcript initialization. Must be the same for prover /// and verifier. pub const TRANSCRIPT_LABEL: &[u8] = b"dusk-network"; @@ -56,6 +82,24 @@ pub const STAKE_CONTRACT: ContractId = reserved(0x2); /// ID of the genesis license contract pub const LICENSE_CONTRACT: ContractId = reserved(0x3); +enum Metadata {} + +#[allow(dead_code)] +impl Metadata { + pub const BLOCK_HEIGHT: &'static str = "block_height"; +} + +enum Query {} + +#[allow(dead_code)] +impl Query { + pub const HASH: &'static str = "hash"; + pub const POSEIDON_HASH: &'static str = "poseidon_hash"; + pub const VERIFY_PROOF: &'static str = "verify_proof"; + pub const VERIFY_SCHNORR: &'static str = "verify_schnorr"; + pub const VERIFY_BLS: &'static str = "verify_bls"; +} + #[inline] const fn reserved(b: u8) -> ContractId { let mut bytes = [0u8; CONTRACT_ID_BYTES]; @@ -66,7 +110,7 @@ const fn reserved(b: u8) -> ContractId { /// Generate a [`ContractId`] address from the given slice of bytes, that is /// also a valid [`BlsScalar`] pub fn gen_contract_id(bytes: &[u8]) -> ContractId { - ContractId::from_bytes(Hasher::digest(bytes).into()) + ContractId::from_bytes(BlsScalar::hash_to_scalar(bytes).into()) } /// Converts a `ContractId` to a `BlsScalar` diff --git a/rusk-abi/src/types.rs b/rusk-abi/src/types.rs deleted file mode 100644 index 92ba1f9ded..0000000000 --- a/rusk-abi/src/types.rs +++ /dev/null @@ -1,121 +0,0 @@ -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. -// -// Copyright (c) DUSK NETWORK. All rights reserved. - -#![allow(dead_code)] - -use execution_core::{ - BlsScalar, JubJubAffine, JubJubExtended, JubJubScalar, PublicKey, -}; - -use bytecheck::CheckBytes; -use rkyv::{Archive, Deserialize, Serialize}; - -pub(crate) enum Query {} - -impl Query { - pub const HASH: &'static str = "hash"; - pub const POSEIDON_HASH: &'static str = "poseidon_hash"; - pub const VERIFY_PROOF: &'static str = "verify_proof"; - pub const VERIFY_SCHNORR: &'static str = "verify_schnorr"; - pub const VERIFY_BLS: &'static str = "verify_bls"; -} - -pub(crate) enum Metadata {} - -impl Metadata { - pub const BLOCK_HEIGHT: &'static str = "block_height"; -} - -/// Enum representing all possible payment configurations. -#[derive(Debug, Clone, Copy, Archive, Deserialize, Serialize)] -#[archive_attr(derive(CheckBytes))] -#[repr(C)] -pub enum PaymentInfo { - /// Only transparent notes are accepted. - Transparent(Option), - /// Only obfuscated notes are accepted. - Obfuscated(Option), - /// Any type of note is accepted. - Any(Option), -} - -/// Enum that represents all possible types of public inputs -#[derive(Debug, Clone, Archive, Serialize, Deserialize)] -#[archive_attr(derive(CheckBytes))] -pub enum PublicInput { - /// A Public Input Point - Point(JubJubAffine), - /// A Public Input BLS Scalar - BlsScalar(BlsScalar), - /// A Public Input JubJub Scalar - JubJubScalar(JubJubScalar), -} - -impl PublicInput { - /// Update the [`blake2b_simd::State`] with the public input. - pub(crate) fn update_hasher(&self, hasher: &mut blake2b_simd::State) { - match self { - Self::Point(p) => { - let u = p.get_u(); - let v = p.get_v(); - - hasher.update(cast_to_bytes(&u.0)); - hasher.update(cast_to_bytes(&v.0)); - } - Self::BlsScalar(s) => { - hasher.update(cast_to_bytes(&s.0)); - } - Self::JubJubScalar(s) => { - let bytes = s.to_bytes(); - hasher.update(&bytes); - } - } - } -} - -fn cast_to_bytes(bytes: &[u64; 4]) -> &[u8; 32] { - // SAFETY: The size of the array is the same, so this is safe. - unsafe { &*(bytes as *const [u64; 4] as *const [u8; 32]) } -} - -impl From for PublicInput { - fn from(s: BlsScalar) -> PublicInput { - Self::BlsScalar(s) - } -} - -impl From for PublicInput { - fn from(n: u64) -> PublicInput { - Self::BlsScalar(n.into()) - } -} - -impl From for PublicInput { - fn from(s: JubJubScalar) -> PublicInput { - Self::JubJubScalar(s) - } -} - -impl From for PublicInput { - fn from(p: JubJubAffine) -> PublicInput { - Self::Point(p) - } -} - -impl From for PublicInput { - fn from(p: JubJubExtended) -> PublicInput { - JubJubAffine::from(p).into() - } -} - -impl From<&T> for PublicInput -where - T: Clone + Into, -{ - fn from(t: &T) -> PublicInput { - t.clone().into() - } -} diff --git a/rusk-abi/tests/lib.rs b/rusk-abi/tests/lib.rs index 1b738c51bf..bfa457a43f 100644 --- a/rusk-abi/tests/lib.rs +++ b/rusk-abi/tests/lib.rs @@ -18,8 +18,6 @@ use execution_core::{ PublicKey, SecretKey, }; use ff::Field; -use rusk_abi::hash::Hasher; -use rusk_abi::PublicInput; use rusk_abi::{ContractData, ContractId, Session, VM}; const POINT_LIMIT: u64 = 0x1000000; @@ -44,7 +42,7 @@ fn hash_host() { assert_eq!( "0x58c751eca2d6a41227e0c52ef579f4688d698b3447a8bcc27fb2831e11d3239e", - format!("{:?}", Hasher::digest(input)) + format!("{:?}", BlsScalar::hash_to_scalar(&input[..])) ); } @@ -306,12 +304,9 @@ fn plonk_proof() { .expect("Proof should verify successfully"); let verifier = verifier.to_bytes(); - let public_inputs: Vec = - expected_pi.into_iter().map(|pi| From::from(pi)).collect(); - let proof = proof.to_bytes().to_vec(); - let arg = (verifier, proof, public_inputs); + let arg = (verifier, proof, expected_pi); let valid: bool = session .call(contract_id, "verify_proof", &arg, POINT_LIMIT) .expect("Query should succeed") @@ -320,8 +315,6 @@ fn plonk_proof() { assert!(valid, "The proof should be valid"); let wrong_public_inputs = vec![BlsScalar::from(0)]; - let wrong_public_inputs: Vec = - wrong_public_inputs.into_iter().map(From::from).collect(); let arg = (arg.0, arg.1, wrong_public_inputs); let valid: bool = session diff --git a/rusk/src/lib/chain/rusk.rs b/rusk/src/lib/chain/rusk.rs index 0ae63b1e9a..6ec6fea890 100644 --- a/rusk/src/lib/chain/rusk.rs +++ b/rusk/src/lib/chain/rusk.rs @@ -34,8 +34,8 @@ use node_data::ledger::{Slash, SpentTransaction, Transaction}; use rusk_abi::dusk::Dusk; use rusk_abi::ContractError::{OutOfGas, Panic}; use rusk_abi::{ - CallReceipt, ContractError, Error as PiecrustError, Event, Session, - STAKE_CONTRACT, TRANSFER_CONTRACT, VM, + CallReceipt, ContractError, Event, PiecrustError, Session, STAKE_CONTRACT, + TRANSFER_CONTRACT, VM, }; use rusk_profile::to_rusk_state_id_path; use tokio::sync::broadcast; diff --git a/rusk/src/lib/error.rs b/rusk/src/lib/error.rs index 9556e268af..98223c791d 100644 --- a/rusk/src/lib/error.rs +++ b/rusk/src/lib/error.rs @@ -10,6 +10,7 @@ use dusk_bytes::Serializable; use execution_core::BlsScalar; use execution_core::{BlsPublicKey, PhoenixError}; use rusk_abi::dusk::Dusk; +use rusk_abi::PiecrustError; #[derive(Debug)] pub enum Error { @@ -38,7 +39,7 @@ pub enum Error { /// Originating from Phoenix. Phoenix(PhoenixError), /// Piecrust VM internal Errors - Vm(rusk_abi::Error), + Vm(PiecrustError), /// IO Errors Io(io::Error), /// Bad block height in coinbase (got, expected) @@ -67,8 +68,8 @@ impl From> for Error { } } -impl From for Error { - fn from(err: rusk_abi::Error) -> Self { +impl From for Error { + fn from(err: PiecrustError) -> Self { Error::Vm(err) } } diff --git a/rusk/src/lib/verifier.rs b/rusk/src/lib/verifier.rs index 3e884c52e9..107a57ce36 100644 --- a/rusk/src/lib/verifier.rs +++ b/rusk/src/lib/verifier.rs @@ -28,9 +28,6 @@ pub static VD_EXEC_4_2: LazyLock> = /// Verifies the proof of the incoming transaction. pub fn verify_proof(tx: &PhoenixTransaction) -> Result { - let pi: Vec = - tx.public_inputs().iter().map(|pi| pi.into()).collect(); - let inputs_len = tx.payload().tx_skeleton.nullifiers.len(); let outputs_len = tx.payload().tx_skeleton.outputs.len(); @@ -46,7 +43,11 @@ pub fn verify_proof(tx: &PhoenixTransaction) -> Result { // Maybe we want to handle internal serialization error too, // currently they map to `false`. - Ok(rusk_abi::verify_proof(vd.to_vec(), tx.proof().to_vec(), pi)) + Ok(rusk_abi::verify_proof( + vd.to_vec(), + tx.proof().to_vec(), + tx.public_inputs(), + )) } /// Verifies the signature of the incoming transaction. diff --git a/rusk/tests/services/contract_deployment.rs b/rusk/tests/services/contract_deployment.rs index e0d3c8db3f..6294725eb5 100644 --- a/rusk/tests/services/contract_deployment.rs +++ b/rusk/tests/services/contract_deployment.rs @@ -13,8 +13,7 @@ use execution_core::transfer::{ContractDeploy, ContractExec}; use rand::prelude::*; use rand::rngs::StdRng; use rusk::{Result, Rusk}; -use rusk_abi::Error::ContractDoesNotExist; -use rusk_abi::{ContractData, ContractId}; +use rusk_abi::{ContractData, ContractId, PiecrustError}; use rusk_recovery_tools::state; use tempfile::tempdir; use test_wallet::{self as wallet, Wallet}; @@ -217,7 +216,7 @@ impl Fixture { u64::MAX, ); match result.err() { - Some(ContractDoesNotExist(_)) => (), + Some(PiecrustError::ContractDoesNotExist(_)) => (), _ => assert!(false), } } diff --git a/test-wallet/src/lib.rs b/test-wallet/src/lib.rs index a652e98772..06e25b647f 100644 --- a/test-wallet/src/lib.rs +++ b/test-wallet/src/lib.rs @@ -18,7 +18,7 @@ use alloc::vec::Vec; use dusk_bytes::{DeserializableSlice, Serializable, Write}; use execution_core::{ stake::StakeData, - transfer::{AccountData, Transaction}, + transfer::{AccountData, Transaction, TRANSFER_TREE_DEPTH}, BlsPublicKey, BlsScalar, BlsSecretKey, Note, SecretKey, ViewKey, }; use poseidon_merkle::Opening as PoseidonOpening; @@ -29,8 +29,6 @@ use sha2::{Digest, Sha256}; pub use imp::*; pub use rusk_prover::UnprovenTransaction; -pub use rusk_abi::POSEIDON_TREE_DEPTH; - /// The maximum size of call data. pub const MAX_CALL_SIZE: usize = rusk_abi::ARGBUF_LEN; @@ -149,7 +147,7 @@ pub trait StateClient { fn fetch_opening( &self, note: &Note, - ) -> Result, Self::Error>; + ) -> Result, Self::Error>; /// Queries the node for the stake of a key. If the key has no stake, a /// `Default` stake info should be returned.