mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-04-28 03:00:18 -04:00
contracts: use proper indexes in money and consensus calls
This commit is contained in:
@@ -82,35 +82,40 @@ pub(crate) fn consensus_stake_process_instruction_v1(
|
||||
call_idx: u32,
|
||||
calls: Vec<DarkLeaf<ContractCall>>,
|
||||
) -> Result<Vec<u8>, ContractError> {
|
||||
let self_ = &calls[call_idx as usize].data;
|
||||
let params: ConsensusStakeParamsV1 = deserialize(&self_.data[1..])?;
|
||||
let self_ = &calls[call_idx as usize];
|
||||
let params: ConsensusStakeParamsV1 = deserialize(&self_.data.data[1..])?;
|
||||
|
||||
// Check previous call is money contract
|
||||
// FIXME: This changes with Money::Fee
|
||||
// Check child call is money contract
|
||||
if call_idx == 0 {
|
||||
msg!("[ConsensusStakeV1] Error: previous_call_idx will be out of bounds");
|
||||
msg!("[ConsensusStakeV1] Error: child_call_idx will be out of bounds");
|
||||
return Err(MoneyError::CallIdxOutOfBounds.into())
|
||||
}
|
||||
|
||||
// Verify previous call corresponds to Money::StakeV1
|
||||
let previous_call_idx = call_idx - 1;
|
||||
let previous = &calls[previous_call_idx as usize].data;
|
||||
if previous.contract_id.inner() != MONEY_CONTRACT_ID.inner() {
|
||||
msg!("[ConsensusStakeV1] Error: Previous contract call is not money contract");
|
||||
return Err(MoneyError::StakePreviousCallNotMoneyContract.into())
|
||||
let child_call_indexes = &self_.children_indexes;
|
||||
if child_call_indexes.len() != 1 {
|
||||
msg!("[ConsensusStakeV1] Error: child_call_idx is missing");
|
||||
return Err(MoneyError::StakeChildCallNotMoneyContract.into())
|
||||
}
|
||||
let child_call_idx = child_call_indexes[0];
|
||||
|
||||
// Verify child call corresponds to Money::StakeV1
|
||||
let child = &calls[child_call_idx].data;
|
||||
if child.contract_id.inner() != MONEY_CONTRACT_ID.inner() {
|
||||
msg!("[ConsensusStakeV1] Error: Child contract call is not money contract");
|
||||
return Err(MoneyError::StakeChildCallNotMoneyContract.into())
|
||||
}
|
||||
|
||||
if previous.data[0] != MoneyFunction::StakeV1 as u8 {
|
||||
msg!("[ConsensusStakeV1] Error: Previous call function mismatch");
|
||||
return Err(MoneyError::PreviousCallFunctionMismatch.into())
|
||||
if child.data[0] != MoneyFunction::StakeV1 as u8 {
|
||||
msg!("[ConsensusStakeV1] Error: Child call function mismatch");
|
||||
return Err(MoneyError::ChildCallFunctionMismatch.into())
|
||||
}
|
||||
|
||||
// Verify that the previous call's input is the same as this one's
|
||||
let previous_params: MoneyStakeParamsV1 = deserialize(&previous.data[1..])?;
|
||||
let previous_input = &previous_params.input;
|
||||
if previous_input != ¶ms.input {
|
||||
msg!("[ConsensusStakeV1] Error: Previous call input mismatch");
|
||||
return Err(MoneyError::PreviousCallInputMismatch.into())
|
||||
// Verify that the child call's input is the same as this one's
|
||||
let child_params: MoneyStakeParamsV1 = deserialize(&child.data[1..])?;
|
||||
let child_input = &child_params.input;
|
||||
if child_input != ¶ms.input {
|
||||
msg!("[ConsensusStakeV1] Error: Child call input mismatch");
|
||||
return Err(MoneyError::ChildCallInputMismatch.into())
|
||||
}
|
||||
|
||||
// Access the necessary databases where there is information to
|
||||
|
||||
@@ -85,8 +85,8 @@ pub(crate) fn consensus_unstake_process_instruction_v1(
|
||||
call_idx: u32,
|
||||
calls: Vec<DarkLeaf<ContractCall>>,
|
||||
) -> Result<Vec<u8>, ContractError> {
|
||||
let self_ = &calls[call_idx as usize].data;
|
||||
let params: ConsensusUnstakeParamsV1 = deserialize(&self_.data[1..])?;
|
||||
let self_ = &calls[call_idx as usize];
|
||||
let params: ConsensusUnstakeParamsV1 = deserialize(&self_.data.data[1..])?;
|
||||
let input = ¶ms.input;
|
||||
|
||||
// Access the necessary databases where there is information to
|
||||
@@ -98,30 +98,36 @@ pub(crate) fn consensus_unstake_process_instruction_v1(
|
||||
// Perform the actual state transition
|
||||
// ===================================
|
||||
|
||||
// Check next call is money contract
|
||||
let next_call_idx = call_idx + 1;
|
||||
if next_call_idx >= calls.len() as u32 {
|
||||
msg!("[ConsensusUnstakeV1] Error: next_call_idx out of bounds");
|
||||
// Check parent call is money contract
|
||||
let parent_call_idx = self_.parent_index;
|
||||
if parent_call_idx.is_none() {
|
||||
msg!("[ConsensusUnstakeV1] Error: parent_call_idx is missing");
|
||||
return Err(MoneyError::UnstakeParentCallNotMoneyContract.into())
|
||||
}
|
||||
let parent_call_idx = parent_call_idx.unwrap();
|
||||
|
||||
if parent_call_idx >= calls.len() {
|
||||
msg!("[ConsensusUnstakeV1] Error: parent_call_idx out of bounds");
|
||||
return Err(MoneyError::CallIdxOutOfBounds.into())
|
||||
}
|
||||
|
||||
let next = &calls[next_call_idx as usize].data;
|
||||
if next.contract_id.inner() != MONEY_CONTRACT_ID.inner() {
|
||||
msg!("[ConsensusUnstakeV1] Error: Next contract call is not money contract");
|
||||
return Err(MoneyError::UnstakeNextCallNotMoneyContract.into())
|
||||
let parent = &calls[parent_call_idx].data;
|
||||
if parent.contract_id.inner() != MONEY_CONTRACT_ID.inner() {
|
||||
msg!("[ConsensusUnstakeV1] Error: Parent contract call is not money contract");
|
||||
return Err(MoneyError::UnstakeParentCallNotMoneyContract.into())
|
||||
}
|
||||
|
||||
// Verify next call corresponds to Money::UnstakeV1
|
||||
if next.data[0] != MoneyFunction::UnstakeV1 as u8 {
|
||||
msg!("[ConsensusUnstakeV1] Error: Next call function mismatch");
|
||||
return Err(MoneyError::NextCallFunctionMismatch.into())
|
||||
// Verify parent call corresponds to Money::UnstakeV1
|
||||
if parent.data[0] != MoneyFunction::UnstakeV1 as u8 {
|
||||
msg!("[ConsensusUnstakeV1] Error: Parent call function mismatch");
|
||||
return Err(MoneyError::ParentCallFunctionMismatch.into())
|
||||
}
|
||||
|
||||
// Verify next call input is the same as this calls input
|
||||
let next_params: MoneyUnstakeParamsV1 = deserialize(&next.data[1..])?;
|
||||
if input != &next_params.input {
|
||||
msg!("[ConsensusUnstakeV1] Error: Next call input mismatch");
|
||||
return Err(MoneyError::NextCallInputMismatch.into())
|
||||
// Verify parent call input is the same as this calls input
|
||||
let parent_params: MoneyUnstakeParamsV1 = deserialize(&parent.data[1..])?;
|
||||
if input != &parent_params.input {
|
||||
msg!("[ConsensusUnstakeV1] Error: Parent call input mismatch");
|
||||
return Err(MoneyError::ParentCallInputMismatch.into())
|
||||
}
|
||||
|
||||
msg!("[ConsensusUnstakeV1] Validating anonymous input");
|
||||
|
||||
@@ -86,8 +86,8 @@ pub(crate) fn money_stake_process_instruction_v1(
|
||||
call_idx: u32,
|
||||
calls: Vec<DarkLeaf<ContractCall>>,
|
||||
) -> Result<Vec<u8>, ContractError> {
|
||||
let self_ = &calls[call_idx as usize].data;
|
||||
let params: MoneyStakeParamsV1 = deserialize(&self_.data[1..])?;
|
||||
let self_ = &calls[call_idx as usize];
|
||||
let params: MoneyStakeParamsV1 = deserialize(&self_.data.data[1..])?;
|
||||
|
||||
// Access the necessary databases where there is information to
|
||||
// validate this state transition.
|
||||
@@ -126,30 +126,36 @@ pub(crate) fn money_stake_process_instruction_v1(
|
||||
return Err(MoneyError::DuplicateNullifier.into())
|
||||
}
|
||||
|
||||
// Check next call is consensus contract
|
||||
let next_call_idx = call_idx + 1;
|
||||
if next_call_idx >= calls.len() as u32 {
|
||||
// Check parent call is consensus contract
|
||||
let parent_call_idx = self_.parent_index;
|
||||
if parent_call_idx.is_none() {
|
||||
msg!("[MoneyStakeV1] Error: parent_call_idx is missing");
|
||||
return Err(MoneyError::StakeParentCallNotConsensusContract.into())
|
||||
}
|
||||
let parent_call_idx = parent_call_idx.unwrap();
|
||||
|
||||
if parent_call_idx >= calls.len() {
|
||||
msg!("[MoneyStakeV1] Error: next_call_idx out of bounds");
|
||||
return Err(MoneyError::CallIdxOutOfBounds.into())
|
||||
}
|
||||
|
||||
// Verify next call corresponds to Consensus::StakeV1 (0x01)
|
||||
let next = &calls[next_call_idx as usize].data;
|
||||
if next.contract_id.inner() != CONSENSUS_CONTRACT_ID.inner() {
|
||||
msg!("[MoneyStakeV1] Error: Next contract call is not consensus contract");
|
||||
return Err(MoneyError::StakeNextCallNotConsensusContract.into())
|
||||
// Verify parent call corresponds to Consensus::StakeV1 (0x01)
|
||||
let parent = &calls[parent_call_idx].data;
|
||||
if parent.contract_id.inner() != CONSENSUS_CONTRACT_ID.inner() {
|
||||
msg!("[MoneyStakeV1] Error: Parent contract call is not consensus contract");
|
||||
return Err(MoneyError::StakeParentCallNotConsensusContract.into())
|
||||
}
|
||||
|
||||
if next.data[0] != 0x01 {
|
||||
msg!("[MoneyStakeV1] Error: Next call function mismatch");
|
||||
return Err(MoneyError::NextCallFunctionMismatch.into())
|
||||
if parent.data[0] != 0x01 {
|
||||
msg!("[MoneyStakeV1] Error: Parent call function mismatch");
|
||||
return Err(MoneyError::ParentCallFunctionMismatch.into())
|
||||
}
|
||||
|
||||
// Verify next call ConsensusInput is the same as this calls input
|
||||
let next_params: ConsensusStakeParamsV1 = deserialize(&next.data[1..])?;
|
||||
if input != &next_params.input {
|
||||
msg!("[MoneyStakeV1] Error: Next call input mismatch");
|
||||
return Err(MoneyError::NextCallInputMismatch.into())
|
||||
// Verify parent call ConsensusInput is the same as this calls input
|
||||
let parent_params: ConsensusStakeParamsV1 = deserialize(&parent.data[1..])?;
|
||||
if input != &parent_params.input {
|
||||
msg!("[MoneyStakeV1] Error: Parent call input mismatch");
|
||||
return Err(MoneyError::ParentCallInputMismatch.into())
|
||||
}
|
||||
|
||||
// At this point the state transition has passed, so we create a state update
|
||||
|
||||
@@ -109,8 +109,8 @@ pub(crate) fn money_transfer_process_instruction_v1(
|
||||
call_idx: u32,
|
||||
calls: Vec<DarkLeaf<ContractCall>>,
|
||||
) -> Result<Vec<u8>, ContractError> {
|
||||
let self_ = &calls[call_idx as usize].data;
|
||||
let params: MoneyTransferParamsV1 = deserialize(&self_.data[1..])?;
|
||||
let self_ = &calls[call_idx as usize];
|
||||
let params: MoneyTransferParamsV1 = deserialize(&self_.data.data[1..])?;
|
||||
|
||||
if params.clear_inputs.len() + params.inputs.len() < 1 {
|
||||
msg!("[TransferV1] Error: No inputs in the call");
|
||||
@@ -188,14 +188,20 @@ pub(crate) fn money_transfer_process_instruction_v1(
|
||||
|
||||
// If spend hook is set, check its correctness
|
||||
if input.spend_hook != pallas::Base::ZERO {
|
||||
let next_call_idx = call_idx + 1;
|
||||
if next_call_idx >= calls.len() as u32 {
|
||||
msg!("[TransferV1] Error: next_call_idx out of bounds (input {})", i);
|
||||
let parent_call_idx = self_.parent_index;
|
||||
if parent_call_idx.is_none() {
|
||||
msg!("[TransferV1] Error: parent_call_idx is missing");
|
||||
return Err(MoneyError::CallIdxOutOfBounds.into())
|
||||
}
|
||||
let parent_call_idx = parent_call_idx.unwrap();
|
||||
|
||||
if parent_call_idx >= calls.len() {
|
||||
msg!("[TransferV1] Error: parent_call_idx out of bounds (input {})", i);
|
||||
return Err(MoneyError::CallIdxOutOfBounds.into())
|
||||
}
|
||||
|
||||
let next = &calls[next_call_idx as usize].data;
|
||||
if next.contract_id.inner() != input.spend_hook {
|
||||
let parent = &calls[parent_call_idx].data;
|
||||
if parent.contract_id.inner() != input.spend_hook {
|
||||
msg!("[TransferV1] Error: Invoked contract call does not match spend hook in input {}", i);
|
||||
return Err(MoneyError::SpendHookMismatch.into())
|
||||
}
|
||||
|
||||
@@ -79,8 +79,8 @@ pub(crate) fn money_unstake_process_instruction_v1(
|
||||
call_idx: u32,
|
||||
calls: Vec<DarkLeaf<ContractCall>>,
|
||||
) -> Result<Vec<u8>, ContractError> {
|
||||
let self_ = &calls[call_idx as usize].data;
|
||||
let params: MoneyUnstakeParamsV1 = deserialize(&self_.data[1..])?;
|
||||
let self_ = &calls[call_idx as usize];
|
||||
let params: MoneyUnstakeParamsV1 = deserialize(&self_.data.data[1..])?;
|
||||
let input = ¶ms.input;
|
||||
let output = ¶ms.output;
|
||||
|
||||
@@ -96,31 +96,37 @@ pub(crate) fn money_unstake_process_instruction_v1(
|
||||
// Perform the actual state transition
|
||||
// ===================================
|
||||
|
||||
// Check previous call is consensus contract
|
||||
// Check child call is consensus contract
|
||||
if call_idx == 0 {
|
||||
msg!("[MoneyUnstakeV1] Error: previous_call_idx will be out of bounds");
|
||||
msg!("[MoneyUnstakeV1] Error: child_call_idx will be out of bounds");
|
||||
return Err(MoneyError::CallIdxOutOfBounds.into())
|
||||
}
|
||||
|
||||
let previous_call_idx = call_idx - 1;
|
||||
let previous = &calls[previous_call_idx as usize].data;
|
||||
if previous.contract_id.inner() != CONSENSUS_CONTRACT_ID.inner() {
|
||||
msg!("[MoneyUnstakeV1] Error: Previous contract call is not consensus contract");
|
||||
return Err(MoneyError::UnstakePreviousCallNotConsensusContract.into())
|
||||
let child_call_indexes = &self_.children_indexes;
|
||||
if child_call_indexes.len() != 1 {
|
||||
msg!("[MoneyUnstakeV1] Error: child_call_idx is missing");
|
||||
return Err(MoneyError::UnstakeChildCallNotConsensusContract.into())
|
||||
}
|
||||
let child_call_idx = child_call_indexes[0];
|
||||
|
||||
let child = &calls[child_call_idx].data;
|
||||
if child.contract_id.inner() != CONSENSUS_CONTRACT_ID.inner() {
|
||||
msg!("[MoneyUnstakeV1] Error: Child contract call is not consensus contract");
|
||||
return Err(MoneyError::UnstakeChildCallNotConsensusContract.into())
|
||||
}
|
||||
|
||||
// Verify previous call corresponds to Consensus::UnstakeV1 (0x04)
|
||||
if previous.data[0] != 0x04 {
|
||||
msg!("[MoneyUnstakeV1] Error: Previous call function mismatch");
|
||||
return Err(MoneyError::PreviousCallFunctionMismatch.into())
|
||||
// Verify child call corresponds to Consensus::UnstakeV1 (0x04)
|
||||
if child.data[0] != 0x04 {
|
||||
msg!("[MoneyUnstakeV1] Error: Child call function mismatch");
|
||||
return Err(MoneyError::ChildCallFunctionMismatch.into())
|
||||
}
|
||||
|
||||
// Verify previous call input is the same as this calls StakeInput
|
||||
let previous_params: ConsensusUnstakeParamsV1 = deserialize(&previous.data[1..])?;
|
||||
let previous_input = &previous_params.input;
|
||||
if previous_input != input {
|
||||
msg!("[MoneyUnstakeV1] Error: Previous call input mismatch");
|
||||
return Err(MoneyError::PreviousCallInputMismatch.into())
|
||||
// Verify child call input is the same as this calls StakeInput
|
||||
let child_params: ConsensusUnstakeParamsV1 = deserialize(&child.data[1..])?;
|
||||
let child_input = &child_params.input;
|
||||
if child_input != input {
|
||||
msg!("[MoneyUnstakeV1] Error: Child call input mismatch");
|
||||
return Err(MoneyError::ChildCallInputMismatch.into())
|
||||
}
|
||||
|
||||
msg!("[MoneyUnstakeV1] Validating anonymous output");
|
||||
|
||||
@@ -20,7 +20,7 @@ use darkfi_sdk::error::ContractError;
|
||||
|
||||
#[derive(Debug, Clone, thiserror::Error)]
|
||||
// TODO: Make generic contract common errors like
|
||||
// NextCallFunctionMismatch
|
||||
// ParentCallFunctionMismatch
|
||||
pub enum MoneyError {
|
||||
#[error("Missing inputs in transfer call")]
|
||||
TransferMissingInputs,
|
||||
@@ -85,32 +85,32 @@ pub enum MoneyError {
|
||||
#[error("Missing nullifier")]
|
||||
StakeMissingNullifier,
|
||||
|
||||
#[error("Next contract call is not consensus contract")]
|
||||
StakeNextCallNotConsensusContract,
|
||||
#[error("Parent contract call is not consensus contract")]
|
||||
StakeParentCallNotConsensusContract,
|
||||
|
||||
#[error("Previous contract call is not money contract")]
|
||||
StakePreviousCallNotMoneyContract,
|
||||
#[error("Child contract call is not money contract")]
|
||||
StakeChildCallNotMoneyContract,
|
||||
|
||||
#[error("Spend hook is not consensus contract")]
|
||||
UnstakeSpendHookNotConsensusContract,
|
||||
|
||||
#[error("Next contract call is not money contract")]
|
||||
UnstakeNextCallNotMoneyContract,
|
||||
#[error("Parent contract call is not money contract")]
|
||||
UnstakeParentCallNotMoneyContract,
|
||||
|
||||
#[error("Previous contract call is not consensus contract")]
|
||||
UnstakePreviousCallNotConsensusContract,
|
||||
#[error("Child contract call is not consensus contract")]
|
||||
UnstakeChildCallNotConsensusContract,
|
||||
|
||||
#[error("Next call function mismatch")]
|
||||
NextCallFunctionMismatch,
|
||||
#[error("Parent call function mismatch")]
|
||||
ParentCallFunctionMismatch,
|
||||
|
||||
#[error("Next call input mismatch")]
|
||||
NextCallInputMismatch,
|
||||
#[error("Parent call input mismatch")]
|
||||
ParentCallInputMismatch,
|
||||
|
||||
#[error("Previous call function mismatch")]
|
||||
PreviousCallFunctionMismatch,
|
||||
#[error("Child call function mismatch")]
|
||||
ChildCallFunctionMismatch,
|
||||
|
||||
#[error("Previous call input mismatch")]
|
||||
PreviousCallInputMismatch,
|
||||
#[error("Child call input mismatch")]
|
||||
ChildCallInputMismatch,
|
||||
|
||||
#[error("Call is not executed on genesis slot")]
|
||||
GenesisCallNonGenesisSlot,
|
||||
@@ -155,15 +155,15 @@ impl From<MoneyError> for ContractError {
|
||||
MoneyError::StakeInputNonNativeToken => Self::Custom(19),
|
||||
MoneyError::StakeMissingSpendHook => Self::Custom(20),
|
||||
MoneyError::StakeMissingNullifier => Self::Custom(21),
|
||||
MoneyError::StakeNextCallNotConsensusContract => Self::Custom(22),
|
||||
MoneyError::StakePreviousCallNotMoneyContract => Self::Custom(23),
|
||||
MoneyError::StakeParentCallNotConsensusContract => Self::Custom(22),
|
||||
MoneyError::StakeChildCallNotMoneyContract => Self::Custom(23),
|
||||
MoneyError::UnstakeSpendHookNotConsensusContract => Self::Custom(24),
|
||||
MoneyError::UnstakeNextCallNotMoneyContract => Self::Custom(25),
|
||||
MoneyError::UnstakePreviousCallNotConsensusContract => Self::Custom(26),
|
||||
MoneyError::NextCallFunctionMismatch => Self::Custom(27),
|
||||
MoneyError::NextCallInputMismatch => Self::Custom(28),
|
||||
MoneyError::PreviousCallFunctionMismatch => Self::Custom(29),
|
||||
MoneyError::PreviousCallInputMismatch => Self::Custom(30),
|
||||
MoneyError::UnstakeParentCallNotMoneyContract => Self::Custom(25),
|
||||
MoneyError::UnstakeChildCallNotConsensusContract => Self::Custom(26),
|
||||
MoneyError::ParentCallFunctionMismatch => Self::Custom(27),
|
||||
MoneyError::ParentCallInputMismatch => Self::Custom(28),
|
||||
MoneyError::ChildCallFunctionMismatch => Self::Custom(29),
|
||||
MoneyError::ChildCallInputMismatch => Self::Custom(30),
|
||||
MoneyError::GenesisCallNonGenesisSlot => Self::Custom(31),
|
||||
MoneyError::MissingNullifier => Self::Custom(32),
|
||||
MoneyError::PoWRewardCallAfterCutoffSlot => Self::Custom(33),
|
||||
|
||||
Reference in New Issue
Block a user