Просмотр исходного кода

contracts: use proper indexes in money and consensus calls

aggstam 2 лет назад
Родитель
Сommit
5711ea1370

+ 25 - 20
src/contract/consensus/src/entrypoint/stake_v1.rs

@@ -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 != &params.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 != &params.input {
+        msg!("[ConsensusStakeV1] Error: Child call input mismatch");
+        return Err(MoneyError::ChildCallInputMismatch.into())
     }
 
     // Access the necessary databases where there is information to

+ 25 - 19
src/contract/consensus/src/entrypoint/unstake_v1.rs

@@ -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 = &params.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");

+ 24 - 18
src/contract/money/src/entrypoint/stake_v1.rs

@@ -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

+ 13 - 7
src/contract/money/src/entrypoint/transfer_v1.rs

@@ -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())
             }

+ 25 - 19
src/contract/money/src/entrypoint/unstake_v1.rs

@@ -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 = &params.input;
     let output = &params.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");

+ 25 - 25
src/contract/money/src/error.rs

@@ -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),