Skip to content

Commit

Permalink
feat: add StakeTransaction (split commit)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tommytrg committed Oct 16, 2023
1 parent b9530af commit c64ab6d
Show file tree
Hide file tree
Showing 13 changed files with 444 additions and 11 deletions.
11 changes: 10 additions & 1 deletion data_structures/src/chain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ use crate::{
superblock::SuperBlockState,
transaction::{
CommitTransaction, DRTransaction, DRTransactionBody, Memoized, MintTransaction,
RevealTransaction, TallyTransaction, Transaction, TxInclusionProof, VTTransaction,
RevealTransaction, StakeTransaction, TallyTransaction, Transaction, TxInclusionProof,
VTTransaction,
},
transaction::{
MemoHash, MemoizedHashable, BETA, COMMIT_WEIGHT, OUTPUT_SIZE, REVEAL_WEIGHT, TALLY_WEIGHT,
Expand Down Expand Up @@ -416,6 +417,8 @@ pub struct BlockTransactions {
pub reveal_txns: Vec<RevealTransaction>,
/// A list of signed tally transactions
pub tally_txns: Vec<TallyTransaction>,
/// A list of signed stake transactions
pub stake_txns: Vec<StakeTransaction>,
}

impl Block {
Expand Down Expand Up @@ -444,6 +447,7 @@ impl Block {
commit_txns: vec![],
reveal_txns: vec![],
tally_txns: vec![],
stake_txns: vec![],
};

/// Function to calculate a merkle tree from a transaction vector
Expand All @@ -468,6 +472,7 @@ impl Block {
commit_hash_merkle_root: merkle_tree_root(&txns.commit_txns),
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),
};

Block::new(
Expand Down Expand Up @@ -682,6 +687,8 @@ pub struct BlockMerkleRoots {
pub reveal_hash_merkle_root: Hash,
/// A 256-bit hash based on all of the tally transactions committed to this block
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,
}

/// Function to calculate a merkle tree from a transaction vector
Expand Down Expand Up @@ -710,6 +717,7 @@ impl BlockMerkleRoots {
commit_hash_merkle_root: merkle_tree_root(&txns.commit_txns),
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),
}
}
}
Expand Down Expand Up @@ -2242,6 +2250,7 @@ impl TransactionsPool {
// be impossible for nodes to broadcast these kinds of transactions.
Transaction::Tally(_tt) => Err(TransactionError::NotValidTransaction),
Transaction::Mint(_mt) => Err(TransactionError::NotValidTransaction),
Transaction::Stake(_mt) => !unimplemented!("contains Stake tx"),
}
}

Expand Down
27 changes: 26 additions & 1 deletion data_structures/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use failure::Fail;
use std::num::ParseIntError;

use crate::chain::{
DataRequestOutput, Epoch, Hash, HashParseError, OutputPointer, PublicKeyHash, RADType,
DataRequestOutput, Epoch, Hash, HashParseError, OutputPointer, PublicKeyHash,
RADType,
};

/// The error type for operations on a [`ChainInfo`](ChainInfo)
Expand Down Expand Up @@ -278,6 +279,21 @@ pub enum TransactionError {
max_weight: u32,
dr_output: Box<DataRequestOutput>,
},
/// Stake weight limit exceeded
#[fail(
display = "Stake ({}) doesn't reach the minimum amount ({})",
min_stake, stake
)]
MinStakeNotReached {
min_stake: u64,
stake: 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 },
#[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 @@ -401,6 +417,15 @@ pub enum BlockError {
weight, max_weight
)]
TotalDataRequestWeightLimitExceeded { weight: u32, max_weight: u32 },
/// Stake weight limit exceeded
#[fail(
display = "Total weight of Stake Transactions in a block ({}) exceeds the limit ({})",
weight, max_weight
)]
TotalStakeWeightLimitExceeded { weight: u32, max_weight: u32 },
/// Repeated operator Stake
#[fail(display = "A single operator is staking more than once: ({}) ", pkh)]
RepeatedStakeOperator { pkh: Hash },
/// Missing expected tallies
#[fail(
display = "{} expected tally transactions are missing in block candidate {}",
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 @@ -801,6 +801,7 @@ mod tests {
commit_hash_merkle_root: default_hash,
reveal_hash_merkle_root: default_hash,
tally_hash_merkle_root: tally_merkle_root_1,
stake_hash_merkle_root: default_hash,
},
proof: default_proof,
bn256_public_key: None,
Expand Down Expand Up @@ -850,6 +851,7 @@ mod tests {
commit_hash_merkle_root: default_hash,
reveal_hash_merkle_root: default_hash,
tally_hash_merkle_root: tally_merkle_root_1,
stake_hash_merkle_root: default_hash,
},
proof: default_proof.clone(),
bn256_public_key: None,
Expand All @@ -865,6 +867,7 @@ mod tests {
commit_hash_merkle_root: default_hash,
reveal_hash_merkle_root: default_hash,
tally_hash_merkle_root: tally_merkle_root_2,
stake_hash_merkle_root: default_hash,
},
proof: default_proof,
bn256_public_key: None,
Expand Down
98 changes: 98 additions & 0 deletions data_structures/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use crate::{
// https://github.com/witnet/WIPs/blob/master/wip-0007.md
pub const INPUT_SIZE: u32 = 133;
pub const OUTPUT_SIZE: u32 = 36;
pub const STAKE_OUTPUT_SIZE: u32 = 105;
pub const COMMIT_WEIGHT: u32 = 400;
pub const REVEAL_WEIGHT: u32 = 200;
pub const TALLY_WEIGHT: u32 = 100;
Expand Down Expand Up @@ -130,6 +131,7 @@ pub enum Transaction {
Reveal(RevealTransaction),
Tally(TallyTransaction),
Mint(MintTransaction),
Stake(StakeTransaction),
}

impl From<VTTransaction> for Transaction {
Expand Down Expand Up @@ -168,6 +170,12 @@ impl From<MintTransaction> for Transaction {
}
}

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

impl AsRef<Transaction> for Transaction {
fn as_ref(&self) -> &Self {
self
Expand Down Expand Up @@ -683,6 +691,80 @@ impl MintTransaction {
}
}

#[derive(Debug, Default, Eq, PartialEq, Clone, Serialize, Deserialize, ProtobufConvert, Hash)]
#[protobuf_convert(pb = "witnet::StakeTransaction")]
pub struct StakeTransaction {
pub body: StakeTransactionBody,
pub signatures: Vec<KeyedSignature>,
}
impl StakeTransaction {
// Creates a new stake transaction.
pub fn new(body: StakeTransactionBody, signatures: Vec<KeyedSignature>) -> Self {
StakeTransaction { body, signatures }
}

/// Returns the weight of a stake 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::StakeTransactionBody")]
pub struct StakeTransactionBody {
pub inputs: Vec<Input>,
pub output: StakeOutput,
pub change: Option<ValueTransferOutput>,

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

impl StakeTransactionBody {
/// Creates a new stake transaction body.
pub fn new(inputs: Vec<Input>, output: StakeOutput, change: Option<ValueTransferOutput>) -> Self {
StakeTransactionBody {
inputs,
output,
change,
hash: MemoHash::new(),
}
}

/// Stake transaction weight. It is calculated as:
///
/// ```text
/// ST_weight = N*INPUT_SIZE+M*OUTPUT_SIZE+STAKE_OUTPUT
///
/// ```
pub fn weight(&self) -> u32 {
let inputs_len = u32::try_from(self.inputs.len()).unwrap_or(u32::MAX);
let inputs_weight = inputs_len.saturating_mul(INPUT_SIZE);
let change_weight = if self.change.is_some() { OUTPUT_SIZE } else { 0 };

inputs_weight.saturating_add(change_weight).saturating_add(STAKE_OUTPUT_SIZE)
}
}

#[derive(Debug, Default, Eq, PartialEq, Clone, Serialize, Deserialize, ProtobufConvert, Hash)]
#[protobuf_convert(pb = "witnet::StakeOutput")]
pub struct StakeOutput {
pub value: u64,
pub authorization: KeyedSignature,
}

impl StakeOutput {
pub fn new(value: u64, authorization: KeyedSignature) -> Self {
StakeOutput {
value,
authorization,
}
}
}

impl MemoizedHashable for VTTransactionBody {
fn hashable_bytes(&self) -> Vec<u8> {
self.to_pb_bytes().unwrap()
Expand Down Expand Up @@ -722,6 +804,15 @@ impl MemoizedHashable for RevealTransactionBody {
&self.hash
}
}
impl MemoizedHashable for StakeTransactionBody {
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 @@ -765,6 +856,12 @@ impl Hashable for RevealTransaction {
}
}

impl Hashable for StakeTransaction {
fn hash(&self) -> Hash {
self.body.hash()
}
}

impl Hashable for Transaction {
fn hash(&self) -> Hash {
match self {
Expand All @@ -774,6 +871,7 @@ impl Hashable for Transaction {
Transaction::Reveal(tx) => tx.hash(),
Transaction::Tally(tx) => tx.hash(),
Transaction::Mint(tx) => tx.hash(),
Transaction::Stake(tx) => tx.hash(),
}
}
}
Expand Down
5 changes: 4 additions & 1 deletion data_structures/src/transaction_factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{
},
error::TransactionError,
fee::{AbsoluteFee, Fee},
transaction::{DRTransactionBody, VTTransactionBody, INPUT_SIZE},
transaction::{DRTransactionBody, StakeTransactionBody, VTTransactionBody, INPUT_SIZE},
utxo_pool::{
NodeUtxos, NodeUtxosRef, OwnUnspentOutputsPool, UnspentOutputsPool, UtxoDiff,
UtxoSelectionStrategy,
Expand Down Expand Up @@ -537,6 +537,9 @@ pub fn transaction_outputs_sum(outputs: &[ValueTransferOutput]) -> Result<u64, T
Ok(total_value)
}

pub fn build_st() -> Result<StakeTransactionBody, TransactionError> {
!unimplemented!()
}
#[cfg(test)]
mod tests {
use std::{
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 @@ -75,6 +75,7 @@ impl fmt::Display for Command {
Transaction::Reveal(_) => f.write_str("REVEAL_TRANSACTION")?,
Transaction::Tally(_) => f.write_str("TALLY_TRANSACTION")?,
Transaction::Mint(_) => f.write_str("MINT_TRANSACTION")?,
Transaction::Stake(_) => f.write_str("STAKE_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 @@ -839,6 +839,8 @@ pub fn build_block(
let mut value_transfer_txns = Vec::new();
let mut data_request_txns = Vec::new();
let mut tally_txns = Vec::new();
// TODO: handle stake tx
let stake_txns = Vec::new();

let min_vt_weight =
VTTransactionBody::new(vec![Input::default()], vec![ValueTransferOutput::default()])
Expand Down Expand Up @@ -1000,13 +1002,15 @@ pub fn build_block(
let commit_hash_merkle_root = merkle_tree_root(&commit_txns);
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 merkle_roots = BlockMerkleRoots {
mint_hash: mint.hash(),
vt_hash_merkle_root,
dr_hash_merkle_root,
commit_hash_merkle_root,
reveal_hash_merkle_root,
tally_hash_merkle_root,
stake_hash_merkle_root,
};

let block_header = BlockHeader {
Expand All @@ -1024,6 +1028,7 @@ pub fn build_block(
commit_txns,
reveal_txns,
tally_txns,
stake_txns,
};

(block_header, txns)
Expand Down
19 changes: 19 additions & 0 deletions schemas/witnet/witnet.proto
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ message Block {
Hash commit_hash_merkle_root = 4;
Hash reveal_hash_merkle_root = 5;
Hash tally_hash_merkle_root = 6;
Hash stake_hash_merkle_root = 7;
}
uint32 signals = 1;
CheckpointBeacon beacon = 2;
Expand All @@ -73,6 +74,7 @@ message Block {
repeated CommitTransaction commit_txns = 4;
repeated RevealTransaction reveal_txns = 5;
repeated TallyTransaction tally_txns = 6;
repeated StakeTransaction stake_txns = 7;
}

BlockHeader block_header = 1;
Expand Down Expand Up @@ -229,6 +231,22 @@ message MintTransaction {
repeated ValueTransferOutput outputs = 2;
}

message StakeOutput {
uint64 value = 1;
KeyedSignature authorization = 2;
}

message StakeTransactionBody {
repeated Input inputs = 1;
StakeOutput output = 2;
ValueTransferOutput change = 3;
}

message StakeTransaction {
StakeTransactionBody body = 1 ;
repeated KeyedSignature signatures = 2;
}

message Transaction {
oneof kind {
VTTransaction ValueTransfer = 1;
Expand All @@ -237,6 +255,7 @@ message Transaction {
RevealTransaction Reveal = 4;
TallyTransaction Tally = 5;
MintTransaction Mint = 6;
StakeTransaction Stake = 7;
}
}

Expand Down
Loading

0 comments on commit c64ab6d

Please sign in to comment.