Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make chain ID available to contracts #2226

Merged
merged 10 commits into from
Aug 31, 2024
9 changes: 9 additions & 0 deletions contracts/host_fn/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ impl HostFnTest {
rusk_abi::verify_bls(msg, pk, sig)
}

pub fn chain_id(&self) -> u8 {
rusk_abi::chain_id()
}

pub fn block_height(&self) -> u64 {
rusk_abi::block_height()
}
Expand Down Expand Up @@ -108,6 +112,11 @@ unsafe fn verify_bls(arg_len: u32) -> u32 {
})
}

#[no_mangle]
unsafe fn chain_id(arg_len: u32) -> u32 {
rusk_abi::wrap_call(arg_len, |_: ()| STATE.chain_id())
}

#[no_mangle]
unsafe fn block_height(arg_len: u32) -> u32 {
rusk_abi::wrap_call(arg_len, |_: ()| STATE.block_height())
Expand Down
3 changes: 2 additions & 1 deletion contracts/license/tests/license.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const LICENSE_CONTRACT_ID: ContractId = {

const POINT_LIMIT: u64 = 0x10000000;
const TEST_OWNER: [u8; 32] = [0; 32];
const CHAIN_ID: u8 = 0xFA;
const USER_ATTRIBUTES: u64 = 545072475273;

static LABEL: &[u8] = b"dusk-network";
Expand All @@ -66,7 +67,7 @@ fn initialize() -> Session {
"../../../target/dusk/wasm32-unknown-unknown/release/license_contract.wasm"
);

let mut session = rusk_abi::new_genesis_session(&vm);
let mut session = rusk_abi::new_genesis_session(&vm, CHAIN_ID);

session
.deploy(
Expand Down
8 changes: 8 additions & 0 deletions contracts/stake/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ impl StakeState {
let nonce = stake.nonce();
let signature = *stake.signature();

if stake.chain_id() != self.chain_id() {
panic!("The stake must target the correct chain");
}

let loaded_stake = self.load_or_create_stake_mut(&account);

// ensure the stake is at least the minimum and that there isn't an
Expand Down Expand Up @@ -456,6 +460,10 @@ impl StakeState {
}
}

fn chain_id(&self) -> u8 {
rusk_abi::chain_id()
}

fn deduct_contract_balance(amount: u64) {
// Update the module balance to reflect the change in the amount
// withdrawable from the contract
Expand Down
5 changes: 3 additions & 2 deletions contracts/stake/tests/common/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use rusk_abi::{ContractData, Session, VM};
use crate::common::utils::update_root;

const OWNER: [u8; 32] = [0; 32];
pub const CHAIN_ID: u8 = 0xFA;
const POINT_LIMIT: u64 = 0x100_000_000;

/// Instantiate the virtual machine with the transfer contract deployed, with a
Expand All @@ -37,7 +38,7 @@ pub fn instantiate<Rng: RngCore + CryptoRng>(
"../../../../target/dusk/wasm32-unknown-unknown/release/stake_contract.wasm"
);

let mut session = rusk_abi::new_genesis_session(vm);
let mut session = rusk_abi::new_genesis_session(vm, CHAIN_ID);

session
.deploy(
Expand Down Expand Up @@ -81,6 +82,6 @@ pub fn instantiate<Rng: RngCore + CryptoRng>(
// sets the block height for all subsequent operations to 1
let base = session.commit().expect("Committing should succeed");

rusk_abi::new_session(vm, base, 1)
rusk_abi::new_session(vm, base, CHAIN_ID, 1)
.expect("Instantiating new session should succeed")
}
10 changes: 10 additions & 0 deletions contracts/stake/tests/common/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ pub fn opening(
.map(|r| r.data)
}

pub fn chain_id(session: &mut Session) -> Result<u8, PiecrustError> {
session
.call(TRANSFER_CONTRACT, "chain_id", &(), POINT_LIMIT)
.map(|r| r.data)
}

pub fn filter_notes_owned_by<I: IntoIterator<Item = Note>>(
vk: PhoenixViewKey,
iter: I,
Expand Down Expand Up @@ -179,6 +185,9 @@ pub fn create_transaction<const I: usize>(
inputs.push((note.clone(), opening));
}

let chain_id =
chain_id(session).expect("Getting the chain ID should succeed");

PhoenixTransaction::new::<StdRng, LocalProver>(
rng,
sender_sk,
Expand All @@ -191,6 +200,7 @@ pub fn create_transaction<const I: usize>(
deposit,
gas_limit,
gas_price,
chain_id,
exec.map(Into::into),
)
.expect("creating the creation shouldn't fail")
Expand Down
11 changes: 7 additions & 4 deletions contracts/stake/tests/stake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use execution_core::{
};

use crate::common::assert::assert_event;
use crate::common::init::instantiate;
use crate::common::init::{instantiate, CHAIN_ID};
use crate::common::utils::*;

const GENESIS_VALUE: u64 = dusk(1_000_000.0);
Expand Down Expand Up @@ -71,8 +71,11 @@ fn stake_withdraw_unstake() {
let input_note_pos = 0;
let deposit = INITIAL_STAKE;

let chain_id =
chain_id(&mut session).expect("Getting the chain ID should succeed");

// Fashion a Stake struct
let stake = Stake::new(&stake_sk, deposit, 1);
let stake = Stake::new(&stake_sk, deposit, 1, chain_id);
let stake_bytes = rkyv::to_bytes::<_, 1024>(&stake)
.expect("Should serialize Stake correctly")
.to_vec();
Expand Down Expand Up @@ -230,7 +233,7 @@ fn stake_withdraw_unstake() {
// set different block height so that the new notes are easily located and
// filtered
let base = session.commit().expect("Committing should succeed");
let mut session = rusk_abi::new_session(vm, base, 2)
let mut session = rusk_abi::new_session(vm, base, CHAIN_ID, 2)
.expect("Instantiating new session should succeed");

let receipt =
Expand Down Expand Up @@ -344,7 +347,7 @@ fn stake_withdraw_unstake() {
// filtered
// sets the block height for all subsequent operations to 1
let base = session.commit().expect("Committing should succeed");
let mut session = rusk_abi::new_session(vm, base, 3)
let mut session = rusk_abi::new_session(vm, base, CHAIN_ID, 3)
.expect("Instantiating new session should succeed");

let receipt =
Expand Down
5 changes: 5 additions & 0 deletions contracts/transfer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ unsafe fn num_notes(arg_len: u32) -> u32 {
rusk_abi::wrap_call(arg_len, |_: ()| STATE.num_notes())
}

#[no_mangle]
unsafe fn chain_id(arg_len: u32) -> u32 {
rusk_abi::wrap_call(arg_len, |_: ()| STATE.chain_id())
}

// "Feeder" queries

#[no_mangle]
Expand Down
12 changes: 12 additions & 0 deletions contracts/transfer/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,10 @@ impl TransferState {
transitory::put_transaction(tx);
let phoenix_tx = transitory::unwrap_phoenix_tx();

if phoenix_tx.chain_id() != self.chain_id() {
panic!("The tx must target the correct chain");
}

// panic if the root is invalid
if !self.root_exists(phoenix_tx.root()) {
panic!("Root not found in the state!");
Expand Down Expand Up @@ -398,6 +402,10 @@ impl TransferState {
transitory::put_transaction(tx);
let moonlight_tx = transitory::unwrap_moonlight_tx();

if moonlight_tx.chain_id() != self.chain_id() {
panic!("The tx must target the correct chain");
}

// check the signature is valid and made by `from`
if !rusk_abi::verify_bls(
moonlight_tx.signature_message(),
Expand Down Expand Up @@ -676,6 +684,10 @@ impl TransferState {
let block_height = rusk_abi::block_height();
self.push_note(block_height, note)
}

pub fn chain_id(&self) -> u8 {
rusk_abi::chain_id()
}
}

fn verify_tx_proof(tx: &PhoenixTransaction) -> bool {
Expand Down
10 changes: 10 additions & 0 deletions contracts/transfer/tests/common/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,12 @@ pub fn opening(
.map(|r| r.data)
}

pub fn chain_id(session: &mut Session) -> Result<u8, PiecrustError> {
session
.call(TRANSFER_CONTRACT, "chain_id", &(), GAS_LIMIT)
.map(|r| r.data)
}

/// Executes a transaction.
/// Returns result containing gas spent.
pub fn execute(
Expand Down Expand Up @@ -214,6 +220,9 @@ pub fn create_phoenix_transaction<const I: usize>(
inputs.push((note.clone(), opening));
}

let chain_id =
chain_id(session).expect("Getting the chain ID should succeed");

PhoenixTransaction::new::<StdRng, LocalProver>(
rng,
sender_sk,
Expand All @@ -226,6 +235,7 @@ pub fn create_phoenix_transaction<const I: usize>(
deposit,
gas_limit,
gas_price,
chain_id,
exec.map(Into::into),
)
.expect("creating the creation shouldn't fail")
Expand Down
23 changes: 20 additions & 3 deletions contracts/transfer/tests/transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
pub mod common;

use crate::common::utils::{
account, contract_balance, create_phoenix_transaction, execute,
account, chain_id, contract_balance, create_phoenix_transaction, execute,
filter_notes_owned_by, leaves_from_height, leaves_from_pos, num_notes,
owned_notes_value, update_root,
};
Expand Down Expand Up @@ -53,6 +53,7 @@ const BOB_ID: ContractId = {
};

const OWNER: [u8; 32] = [0; 32];
const CHAIN_ID: u8 = 0xFA;

/// Instantiate the virtual machine with the transfer contract deployed, with a
/// single note carrying the `GENESIS_VALUE` owned by the given public key.
Expand All @@ -72,7 +73,7 @@ fn instantiate<Rng: RngCore + CryptoRng>(
"../../../target/dusk/wasm32-unknown-unknown/release/alice.wasm"
);

let mut session = rusk_abi::new_genesis_session(vm);
let mut session = rusk_abi::new_genesis_session(vm, CHAIN_ID);

session
.deploy(
Expand Down Expand Up @@ -137,7 +138,7 @@ fn instantiate<Rng: RngCore + CryptoRng>(
// sets the block height for all subsequent operations to 1
let base = session.commit().expect("Committing should succeed");

rusk_abi::new_session(vm, base, 1)
rusk_abi::new_session(vm, base, CHAIN_ID, 1)
.expect("Instantiating new session should succeed")
}

Expand Down Expand Up @@ -265,6 +266,9 @@ fn moonlight_transfer() {
"The receiver account should be empty"
);

let chain_id =
chain_id(session).expect("Getting the chain ID should succeed");

let transaction = MoonlightTransaction::new(
&moonlight_sender_sk,
Some(moonlight_receiver_pk),
Expand All @@ -273,6 +277,7 @@ fn moonlight_transfer() {
GAS_LIMIT,
LUX,
sender_account.nonce + 1,
chain_id,
None::<ContractExec>,
);

Expand Down Expand Up @@ -396,6 +401,9 @@ fn moonlight_alice_ping() {
"The account should have the genesis value"
);

let chain_id =
chain_id(session).expect("Getting the chain ID should succeed");

let transaction = MoonlightTransaction::new(
&moonlight_sk,
None,
Expand All @@ -404,6 +412,7 @@ fn moonlight_alice_ping() {
GAS_LIMIT,
LUX,
acc.nonce + 1,
chain_id,
contract_call,
);

Expand Down Expand Up @@ -750,6 +759,9 @@ fn moonlight_to_phoenix_swap() {
.to_vec(),
};

let chain_id =
chain_id(session).expect("Getting the chain ID should succeed");

let tx = MoonlightTransaction::new(
&moonlight_sk,
None,
Expand All @@ -758,6 +770,7 @@ fn moonlight_to_phoenix_swap() {
GAS_LIMIT,
LUX,
nonce,
chain_id,
Some(contract_call),
);

Expand Down Expand Up @@ -849,6 +862,9 @@ fn swap_wrong_contract_targeted() {
.to_vec(),
};

let chain_id =
chain_id(session).expect("Getting the chain ID should succeed");

let tx = MoonlightTransaction::new(
&moonlight_sk,
None,
Expand All @@ -857,6 +873,7 @@ fn swap_wrong_contract_targeted() {
GAS_LIMIT,
LUX,
nonce,
chain_id,
Some(contract_call),
);

Expand Down
20 changes: 17 additions & 3 deletions execution-core/src/stake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,26 @@ pub const fn next_epoch(block_height: u64) -> u64 {
#[derive(Debug, Clone, PartialEq, Eq, Archive, Serialize, Deserialize)]
#[archive_attr(derive(CheckBytes))]
pub struct Stake {
chain_id: u8,
account: BlsPublicKey,
value: u64,
nonce: u64,
signature: BlsSignature,
}

impl Stake {
const MESSAGE_SIZE: usize = BlsPublicKey::SIZE + u64::SIZE + u64::SIZE;
const MESSAGE_SIZE: usize = 1 + BlsPublicKey::SIZE + u64::SIZE + u64::SIZE;

/// Create a new stake.
#[must_use]
pub fn new(sk: &BlsSecretKey, value: u64, nonce: u64) -> Self {
pub fn new(
sk: &BlsSecretKey,
value: u64,
nonce: u64,
chain_id: u8,
) -> Self {
let mut stake = Stake {
chain_id,
account: BlsPublicKey::from(sk),
value,
nonce,
Expand Down Expand Up @@ -91,6 +98,12 @@ impl Stake {
self.nonce
}

/// Returns the chain ID of the stake.
#[must_use]
pub fn chain_id(&self) -> u8 {
self.chain_id
}

/// Signature of the stake.
#[must_use]
pub fn signature(&self) -> &BlsSignature {
Expand All @@ -102,7 +115,8 @@ impl Stake {
pub fn signature_message(&self) -> [u8; Self::MESSAGE_SIZE] {
let mut bytes = [0u8; Self::MESSAGE_SIZE];

let mut offset = 0;
bytes[0] = self.chain_id;
let mut offset = 1;

bytes[offset..offset + BlsPublicKey::SIZE]
.copy_from_slice(&self.account.to_bytes());
Expand Down
Loading
Loading