Skip to content

Commit

Permalink
f unstake
Browse files Browse the repository at this point in the history
  • Loading branch information
Tommytrg committed Oct 17, 2023
1 parent e724019 commit c639a7a
Show file tree
Hide file tree
Showing 10 changed files with 284 additions and 4 deletions.
10 changes: 9 additions & 1 deletion data_structures/src/chain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ use crate::{
transaction::{
CommitTransaction, DRTransaction, DRTransactionBody, Memoized, MintTransaction,
RevealTransaction, StakeTransaction, TallyTransaction, Transaction, TxInclusionProof,
VTTransaction,
UnstakeTransaction, VTTransaction,
},
transaction::{
MemoHash, MemoizedHashable, BETA, COMMIT_WEIGHT, OUTPUT_SIZE, REVEAL_WEIGHT, TALLY_WEIGHT,
Expand Down Expand Up @@ -419,6 +419,8 @@ pub struct BlockTransactions {
pub tally_txns: Vec<TallyTransaction>,
/// A list of signed stake transactions
pub stake_txns: Vec<StakeTransaction>,
/// A list of signed unstake transactions
pub unstake_txns: Vec<UnstakeTransaction>,
}

impl Block {
Expand Down Expand Up @@ -448,6 +450,7 @@ impl Block {
reveal_txns: vec![],
tally_txns: vec![],
stake_txns: vec![],
unstake_txns: vec![],
};

/// Function to calculate a merkle tree from a transaction vector
Expand All @@ -473,6 +476,7 @@ impl Block {
reveal_hash_merkle_root: merkle_tree_root(&txns.reveal_txns),
tally_hash_merkle_root: merkle_tree_root(&txns.tally_txns),
stake_hash_merkle_root: merkle_tree_root(&txns.stake_txns),
unstake_hash_merkle_root: merkle_tree_root(&txns.unstake_txns),
};

Block::new(
Expand Down Expand Up @@ -689,6 +693,8 @@ pub struct BlockMerkleRoots {
pub tally_hash_merkle_root: Hash,
/// A 256-bit hash based on all of the stake transactions committed to this block
pub stake_hash_merkle_root: Hash,
/// A 256-bit hash based on all of the unstake transactions committed to this block
pub unstake_hash_merkle_root: Hash,
}

/// Function to calculate a merkle tree from a transaction vector
Expand Down Expand Up @@ -718,6 +724,7 @@ impl BlockMerkleRoots {
reveal_hash_merkle_root: merkle_tree_root(&txns.reveal_txns),
tally_hash_merkle_root: merkle_tree_root(&txns.tally_txns),
stake_hash_merkle_root: merkle_tree_root(&txns.stake_txns),
unstake_hash_merkle_root: merkle_tree_root(&txns.unstake_txns),
}
}
}
Expand Down Expand Up @@ -2251,6 +2258,7 @@ impl TransactionsPool {
Transaction::Tally(_tt) => Err(TransactionError::NotValidTransaction),
Transaction::Mint(_mt) => Err(TransactionError::NotValidTransaction),
Transaction::Stake(_mt) => !unimplemented!("contains Stake tx"),
Transaction::Unstake(_mt) => !unimplemented!("contains Unstake tx"),
}
}

Expand Down
26 changes: 26 additions & 0 deletions data_structures/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,9 +284,29 @@ pub enum TransactionError {
min_stake, stake
)]
MinStakeNotReached { min_stake: u64, stake: u64 },

/// Unstaking more than the total staked
#[fail(
display = "Unstaking ({}) more than the total staked ({})",
unstake, stake
)]
UnstakingMoreThanStaked { stake: u64, unstake: u64 },
/// An stake output with zero value does not make sense
#[fail(display = "Transaction {} has a zero value stake output", tx_hash)]
ZeroValueStakeOutput { tx_hash: Hash },
/// Invalid unstake signature
#[fail(display = "Invalid unstake signature: ({}), withdrawal ({}), operator ({})", signature, withdrawal, operator)]
InvalidUnstakeSignature {
signature: Hash,
withdrawal: Hash,
operator: Hash,
},
/// Invalid unstake time_lock
#[fail(display = "The unstake timelock: ({}) is lower than the minimum unstaking delay ({})", time_lock, unstaking_delay_seconds)]
InvalidUnstakeTimelock {
time_lock: u64,
unstaking_delay_seconds: u32,
},
#[fail(
display = "The reward-to-collateral ratio for this data request is {}, but must be equal or less than {}",
reward_collateral_ratio, required_reward_collateral_ratio
Expand Down Expand Up @@ -416,6 +436,12 @@ pub enum BlockError {
weight, max_weight
)]
TotalStakeWeightLimitExceeded { weight: u32, max_weight: u32 },
/// Unstake weight limit exceeded
#[fail(
display = "Total weight of Unstake Transactions in a block ({}) exceeds the limit ({})",
weight, max_weight
)]
TotalUnstakeWeightLimitExceeded { weight: u32, max_weight: u32 },
/// Repeated operator Stake
#[fail(display = "A single operator is staking more than once: ({}) ", pkh)]
RepeatedStakeOperator { pkh: Hash },
Expand Down
3 changes: 3 additions & 0 deletions data_structures/src/superblock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,7 @@ mod tests {
reveal_hash_merkle_root: default_hash,
tally_hash_merkle_root: tally_merkle_root_1,
stake_hash_merkle_root: default_hash,
unstake_hash_merkle_root: default_hash,
},
proof: default_proof,
bn256_public_key: None,
Expand Down Expand Up @@ -852,6 +853,7 @@ mod tests {
reveal_hash_merkle_root: default_hash,
tally_hash_merkle_root: tally_merkle_root_1,
stake_hash_merkle_root: default_hash,
unstake_hash_merkle_root: default_hash,
},
proof: default_proof.clone(),
bn256_public_key: None,
Expand All @@ -868,6 +870,7 @@ mod tests {
reveal_hash_merkle_root: default_hash,
tally_hash_merkle_root: tally_merkle_root_2,
stake_hash_merkle_root: default_hash,
unstake_hash_merkle_root: default_hash,
},
proof: default_proof,
bn256_public_key: None,
Expand Down
78 changes: 77 additions & 1 deletion data_structures/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::{
proto::{schema::witnet, ProtobufConvert},
vrf::DataRequestEligibilityClaim,
};

pub const UNSTAKE_TRANSACTION_WEIGHT: u32 = 153;
// These constants were calculated in:
// https://github.com/witnet/WIPs/blob/master/wip-0007.md
pub const INPUT_SIZE: u32 = 133;
Expand Down Expand Up @@ -132,6 +132,7 @@ pub enum Transaction {
Tally(TallyTransaction),
Mint(MintTransaction),
Stake(StakeTransaction),
Unstake(UnstakeTransaction),
}

impl From<VTTransaction> for Transaction {
Expand Down Expand Up @@ -176,6 +177,12 @@ impl From<StakeTransaction> for Transaction {
}
}

impl From<UnstakeTransaction> for Transaction {
fn from(transaction: UnstakeTransaction) -> Self {
Self::Unstake(transaction)
}
}

impl AsRef<Transaction> for Transaction {
fn as_ref(&self) -> &Self {
self
Expand Down Expand Up @@ -775,6 +782,60 @@ impl StakeOutput {
}
}

#[derive(Debug, Default, Eq, PartialEq, Clone, Serialize, Deserialize, ProtobufConvert, Hash)]
#[protobuf_convert(pb = "witnet::UnstakeTransaction")]
pub struct UnstakeTransaction {
pub body: UnstakeTransactionBody,
pub signature: KeyedSignature,
}
impl UnstakeTransaction {
// Creates a new unstake transaction.
pub fn new(body: UnstakeTransactionBody, signature: KeyedSignature) -> Self {
UnstakeTransaction { body, signature }
}

/// Returns the weight of a unstake transaction.
/// This is the weight that will be used to calculate
/// how many transactions can fit inside one block
pub fn weight(&self) -> u32 {
self.body.weight()
}
}

#[derive(Debug, Default, Eq, PartialEq, Clone, Serialize, Deserialize, ProtobufConvert, Hash)]
#[protobuf_convert(pb = "witnet::UnstakeTransactionBody")]
pub struct UnstakeTransactionBody {
pub operator: PublicKeyHash,
pub withdrawal: ValueTransferOutput,
pub change: Option<ValueTransferOutput>,

#[protobuf_convert(skip)]
#[serde(skip)]
hash: MemoHash,
}

impl UnstakeTransactionBody {
/// Creates a new stake transaction body.
pub fn new(operator: PublicKeyHash, withdrawal: ValueTransferOutput, change: Option<ValueTransferOutput>) -> Self {
UnstakeTransactionBody {
operator,
withdrawal,
change,
hash: MemoHash::new(),
}
}

/// Stake transaction weight. It is calculated as:
///
/// ```text
/// ST_weight = 153
///
/// ```
pub fn weight(&self) -> u32 {
UNSTAKE_TRANSACTION_WEIGHT
}
}

impl MemoizedHashable for VTTransactionBody {
fn hashable_bytes(&self) -> Vec<u8> {
self.to_pb_bytes().unwrap()
Expand Down Expand Up @@ -823,6 +884,15 @@ impl MemoizedHashable for StakeTransactionBody {
&self.hash
}
}
impl MemoizedHashable for UnstakeTransactionBody {
fn hashable_bytes(&self) -> Vec<u8> {
self.to_pb_bytes().unwrap()
}

fn memoized_hash(&self) -> &MemoHash {
&self.hash
}
}
impl MemoizedHashable for TallyTransaction {
fn hashable_bytes(&self) -> Vec<u8> {
let Hash::SHA256(data_bytes) = self.data_poi_hash();
Expand Down Expand Up @@ -871,6 +941,11 @@ impl Hashable for StakeTransaction {
self.body.hash()
}
}
impl Hashable for UnstakeTransaction {
fn hash(&self) -> Hash {
self.body.hash()
}
}

impl Hashable for Transaction {
fn hash(&self) -> Hash {
Expand All @@ -882,6 +957,7 @@ impl Hashable for Transaction {
Transaction::Tally(tx) => tx.hash(),
Transaction::Mint(tx) => tx.hash(),
Transaction::Stake(tx) => tx.hash(),
Transaction::Unstake(tx) => tx.hash(),
}
}
}
Expand Down
1 change: 1 addition & 0 deletions data_structures/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ impl fmt::Display for Command {
Transaction::Tally(_) => f.write_str("TALLY_TRANSACTION")?,
Transaction::Mint(_) => f.write_str("MINT_TRANSACTION")?,
Transaction::Stake(_) => f.write_str("STAKE_TRANSACTION")?,
Transaction::Unstake(_) => f.write_str("UNSTAKE_TRANSACTION")?,
}
write!(f, ": {}", tx.hash())
}
Expand Down
5 changes: 5 additions & 0 deletions node/src/actors/chain_manager/mining.rs
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,8 @@ pub fn build_block(
let mut tally_txns = Vec::new();
// TODO: handle stake tx
let stake_txns = Vec::new();
// TODO: handle unstake tx
let unstake_txns = Vec::new();

let min_vt_weight =
VTTransactionBody::new(vec![Input::default()], vec![ValueTransferOutput::default()])
Expand Down Expand Up @@ -1003,6 +1005,7 @@ pub fn build_block(
let reveal_hash_merkle_root = merkle_tree_root(&reveal_txns);
let tally_hash_merkle_root = merkle_tree_root(&tally_txns);
let stake_hash_merkle_root = merkle_tree_root(&stake_txns);
let unstake_hash_merkle_root = merkle_tree_root(&unstake_txns);
let merkle_roots = BlockMerkleRoots {
mint_hash: mint.hash(),
vt_hash_merkle_root,
Expand All @@ -1011,6 +1014,7 @@ pub fn build_block(
reveal_hash_merkle_root,
tally_hash_merkle_root,
stake_hash_merkle_root,
unstake_hash_merkle_root,
};

let block_header = BlockHeader {
Expand All @@ -1029,6 +1033,7 @@ pub fn build_block(
reveal_txns,
tally_txns,
stake_txns,
unstake_txns,
};

(block_header, txns)
Expand Down
14 changes: 14 additions & 0 deletions schemas/witnet/witnet.proto
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ message Block {
Hash reveal_hash_merkle_root = 5;
Hash tally_hash_merkle_root = 6;
Hash stake_hash_merkle_root = 7;
Hash unstake_hash_merkle_root = 8;
}
uint32 signals = 1;
CheckpointBeacon beacon = 2;
Expand All @@ -75,6 +76,7 @@ message Block {
repeated RevealTransaction reveal_txns = 5;
repeated TallyTransaction tally_txns = 6;
repeated StakeTransaction stake_txns = 7;
repeated UnstakeTransaction unstake_txns = 8;
}

BlockHeader block_header = 1;
Expand Down Expand Up @@ -247,6 +249,17 @@ message StakeTransaction {
repeated KeyedSignature signatures = 2;
}

message UnstakeTransactionBody {
PublicKeyHash operator = 1;
ValueTransferOutput withdrawal = 2;
ValueTransferOutput change = 3;
}

message UnstakeTransaction {
UnstakeTransactionBody body = 1 ;
KeyedSignature signature = 2;
}

message Transaction {
oneof kind {
VTTransaction ValueTransfer = 1;
Expand All @@ -256,6 +269,7 @@ message Transaction {
TallyTransaction Tally = 5;
MintTransaction Mint = 6;
StakeTransaction Stake = 7;
UnstakeTransaction Unstake = 8;
}
}

Expand Down
Loading

0 comments on commit c639a7a

Please sign in to comment.