mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-04-28 03:00:18 -04:00
contract/consensus: Clean up and reorder UnstakeV1 state transition
This commit is contained in:
@@ -19,8 +19,8 @@
|
||||
use darkfi_money_contract::{
|
||||
error::MoneyError,
|
||||
model::{ConsensusUnstakeParamsV1, ConsensusUnstakeUpdateV1, MoneyUnstakeParamsV1},
|
||||
CONSENSUS_CONTRACT_NULLIFIERS_TREE, CONSENSUS_CONTRACT_UNSTAKED_COINS_TREE,
|
||||
CONSENSUS_CONTRACT_UNSTAKED_COIN_ROOTS_TREE, CONSENSUS_CONTRACT_ZKAS_BURN_NS_V1,
|
||||
MoneyFunction, CONSENSUS_CONTRACT_NULLIFIERS_TREE, CONSENSUS_CONTRACT_UNSTAKED_COIN_ROOTS_TREE,
|
||||
CONSENSUS_CONTRACT_ZKAS_BURN_NS_V1,
|
||||
};
|
||||
use darkfi_sdk::{
|
||||
crypto::{pasta_prelude::*, ContractId, MONEY_CONTRACT_ID},
|
||||
@@ -33,7 +33,7 @@ use darkfi_sdk::{
|
||||
};
|
||||
use darkfi_serial::{deserialize, serialize, Encodable, WriteExt};
|
||||
|
||||
use crate::{error::ConsensusError, model::calculate_grace_period, ConsensusFunction};
|
||||
use crate::{error::ConsensusError, model::GRACE_PERIOD, ConsensusFunction};
|
||||
|
||||
/// `get_metadata` function for `Consensus::UnstakeV1`
|
||||
pub(crate) fn consensus_unstake_get_metadata_v1(
|
||||
@@ -50,11 +50,10 @@ pub(crate) fn consensus_unstake_get_metadata_v1(
|
||||
// Public keys for the transaction signatures we have to verify
|
||||
let signature_pubkeys = vec![input.signature_public];
|
||||
|
||||
// Grab the pedersen commitments and signature pubkeys from the
|
||||
// Grab the pedersen commitment and signature pubkey coordinates from the
|
||||
// anonymous input
|
||||
let value_coords = input.value_commit.to_affine().coordinates().unwrap();
|
||||
let (sig_x, sig_y) = input.signature_public.xy();
|
||||
let epoch_palas = pallas::Base::from(input.epoch);
|
||||
|
||||
// It is very important that these are in the same order as the
|
||||
// `constrain_instance` calls in the zkas code.
|
||||
@@ -63,7 +62,7 @@ pub(crate) fn consensus_unstake_get_metadata_v1(
|
||||
CONSENSUS_CONTRACT_ZKAS_BURN_NS_V1.to_string(),
|
||||
vec![
|
||||
input.nullifier.inner(),
|
||||
epoch_palas,
|
||||
pallas::Base::from(input.epoch),
|
||||
sig_x,
|
||||
sig_y,
|
||||
input.merkle_root.inner(),
|
||||
@@ -76,7 +75,6 @@ pub(crate) fn consensus_unstake_get_metadata_v1(
|
||||
let mut metadata = vec![];
|
||||
zk_public_inputs.encode(&mut metadata)?;
|
||||
signature_pubkeys.encode(&mut metadata)?;
|
||||
|
||||
Ok(metadata)
|
||||
}
|
||||
|
||||
@@ -93,42 +91,12 @@ pub(crate) fn consensus_unstake_process_instruction_v1(
|
||||
// Access the necessary databases where there is information to
|
||||
// validate this state transition.
|
||||
let nullifiers_db = db_lookup(cid, CONSENSUS_CONTRACT_NULLIFIERS_TREE)?;
|
||||
let unstaked_coins_db = db_lookup(cid, CONSENSUS_CONTRACT_UNSTAKED_COINS_TREE)?;
|
||||
let unstaked_coin_roots_db = db_lookup(cid, CONSENSUS_CONTRACT_UNSTAKED_COIN_ROOTS_TREE)?;
|
||||
|
||||
// ===================================
|
||||
// Perform the actual state transition
|
||||
// ===================================
|
||||
|
||||
msg!("[ConsensusUnstakeV1] Validating anonymous input");
|
||||
|
||||
// The coin has passed through the grace period and is allowed to get unstaked.
|
||||
if get_verifying_slot_epoch() - input.epoch <= calculate_grace_period() {
|
||||
msg!("[ConsensusUnstakeV1] Error: Coin is not allowed to get unstaked yet");
|
||||
return Err(ConsensusError::CoinStillInGracePeriod.into())
|
||||
}
|
||||
|
||||
/*
|
||||
// Check that the coin exists in unstake set.
|
||||
if !db_contains_key(unstaked_coins_db, &serialize(&input.coin))? {
|
||||
msg!("[GenesisStakeV1] Error: Unstaked coin is not in unstake set");
|
||||
return Err(ConsensusError::CoinNotInUnstakeSet.into())
|
||||
}
|
||||
*/
|
||||
|
||||
// The Merkle root is used to know whether this is an unstaked coin that
|
||||
// existed in a previous state.
|
||||
if !db_contains_key(unstaked_coin_roots_db, &serialize(&input.merkle_root))? {
|
||||
msg!("[ConsensusUnstakeV1] Error: Merkle root not found in previous state");
|
||||
return Err(MoneyError::TransferMerkleRootNotFound.into())
|
||||
}
|
||||
|
||||
// The nullifiers should not already exist. It is the double-spend protection.
|
||||
if db_contains_key(nullifiers_db, &serialize(&input.nullifier))? {
|
||||
msg!("[ConsensusUnstakeV1] Error: Duplicate nullifier found");
|
||||
return Err(MoneyError::DuplicateNullifier.into())
|
||||
}
|
||||
|
||||
// Check next call is money contract
|
||||
let next_call_idx = call_idx + 1;
|
||||
if next_call_idx >= calls.len() as u32 {
|
||||
@@ -142,26 +110,44 @@ pub(crate) fn consensus_unstake_process_instruction_v1(
|
||||
return Err(MoneyError::UnstakeNextCallNotMoneyContract.into())
|
||||
}
|
||||
|
||||
// Verify next call corresponds to Money::UnstakeV1 (0x07)
|
||||
if next.data[0] != 0x07 {
|
||||
// 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 next call StakeInput is the same as this calls input
|
||||
// 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())
|
||||
}
|
||||
|
||||
msg!("[ConsensusUnstakeV1] Validating anonymous input");
|
||||
// The coin has passed through the grace period and is allowed to get unstaked.
|
||||
if get_verifying_slot_epoch() - input.epoch <= GRACE_PERIOD {
|
||||
msg!("[ConsensusUnstakeV1] Error: Coin is not allowed to get unstaked yet");
|
||||
return Err(ConsensusError::CoinStillInGracePeriod.into())
|
||||
}
|
||||
|
||||
// The Merkle root is used to know whether this is an unstaked coin that
|
||||
// existed in a previous state.
|
||||
if !db_contains_key(unstaked_coin_roots_db, &serialize(&input.merkle_root))? {
|
||||
msg!("[ConsensusUnstakeV1] Error: Merkle root not found in previous state");
|
||||
return Err(MoneyError::TransferMerkleRootNotFound.into())
|
||||
}
|
||||
|
||||
// The nullifiers should not already exist. It is the double-spend protection.
|
||||
if db_contains_key(nullifiers_db, &serialize(&input.nullifier))? {
|
||||
msg!("[ConsensusUnstakeV1] Error: Duplicate nullifier found");
|
||||
return Err(MoneyError::DuplicateNullifier.into())
|
||||
}
|
||||
|
||||
// At this point the state transition has passed, so we create a state update
|
||||
let update = ConsensusUnstakeUpdateV1 { nullifier: input.nullifier };
|
||||
let mut update_data = vec![];
|
||||
update_data.write_u8(ConsensusFunction::UnstakeV1 as u8)?;
|
||||
update.encode(&mut update_data)?;
|
||||
|
||||
// and return it
|
||||
Ok(update_data)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user