Skip to content

Commit e6c963e

Browse files
committed
feat(node): add stake transaction block weight checks
close #2434
1 parent cf3885f commit e6c963e

File tree

2 files changed

+60
-5
lines changed

2 files changed

+60
-5
lines changed

node/src/actors/chain_manager/mining.rs

+58-5
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ use actix::{
1616
use ansi_term::Color::{White, Yellow};
1717
use futures::future::{try_join_all, FutureExt};
1818

19-
use witnet_config::defaults::PSEUDO_CONSENSUS_CONSTANTS_WIP0027_COLLATERAL_AGE;
19+
use witnet_config::defaults::{
20+
PSEUDO_CONSENSUS_CONSTANTS_POS_MAX_STAKE_BLOCK_WEIGHT,
21+
PSEUDO_CONSENSUS_CONSTANTS_WIP0027_COLLATERAL_AGE,
22+
};
2023
use witnet_data_structures::{
2124
chain::{
2225
tapi::{after_second_hard_fork, ActiveWips},
@@ -115,6 +118,7 @@ impl ChainManager {
115118
let chain_info = self.chain_state.chain_info.as_mut().unwrap();
116119
let max_vt_weight = chain_info.consensus_constants.max_vt_weight;
117120
let max_dr_weight = chain_info.consensus_constants.max_dr_weight;
121+
let max_st_weight = PSEUDO_CONSENSUS_CONSTANTS_POS_MAX_STAKE_BLOCK_WEIGHT;
118122
let mining_bf = chain_info.consensus_constants.mining_backup_factor;
119123
let mining_rf = chain_info.consensus_constants.mining_replication_factor;
120124
let collateral_minimum = chain_info.consensus_constants.collateral_minimum;
@@ -232,6 +236,7 @@ impl ChainManager {
232236
),
233237
max_vt_weight,
234238
max_dr_weight,
239+
max_st_weight,
235240
beacon,
236241
eligibility_claim,
237242
&tally_transactions,
@@ -814,11 +819,13 @@ impl ChainManager {
814819
/// Build a new Block using the supplied leadership proof and by filling transactions from the
815820
/// `transaction_pool`
816821
/// Returns an unsigned block!
822+
/// TODO: simplify function signature, e.g. through merging multiple related fields into new data structures.
817823
#[allow(clippy::too_many_arguments)]
818824
pub fn build_block(
819825
pools_ref: (&mut TransactionsPool, &UnspentOutputsPool, &DataRequestPool),
820826
max_vt_weight: u32,
821827
max_dr_weight: u32,
828+
max_st_weight: u32,
822829
beacon: CheckpointBeacon,
823830
proof: BlockEligibilityClaim,
824831
tally_transactions: &[TallyTransaction],
@@ -842,18 +849,21 @@ pub fn build_block(
842849
let mut transaction_fees: u64 = 0;
843850
let mut vt_weight: u32 = 0;
844851
let mut dr_weight: u32 = 0;
852+
let mut st_weight: u32 = 0;
845853
let mut value_transfer_txns = Vec::new();
846854
let mut data_request_txns = Vec::new();
847855
let mut tally_txns = Vec::new();
848-
// TODO: handle stake tx
849-
let stake_txns = Vec::new();
856+
let mut stake_txns = Vec::new();
850857
// TODO: handle unstake tx
851858
let unstake_txns = Vec::new();
852859

860+
// Calculate the base weight for different types of transactions, to know when to give up trying to fit more
861+
// transactions into a block
853862
let min_vt_weight =
854863
VTTransactionBody::new(vec![Input::default()], vec![ValueTransferOutput::default()])
855864
.weight();
856-
// Currently only value transfer transactions weight is taking into account
865+
let min_st_weight =
866+
StakeTransactionBody::new(vec![Input::default()], Default::default(), None).weight();
857867

858868
for vt_tx in transactions_pool.vt_iter() {
859869
let transaction_weight = vt_tx.weight();
@@ -868,7 +878,7 @@ pub fn build_block(
868878
}
869879
};
870880

871-
let new_vt_weight = vt_weight.saturating_add(transaction_weight);
881+
let new_vt_weight = st_weight.saturating_add(transaction_weight);
872882
if new_vt_weight <= max_vt_weight {
873883
update_utxo_diff(
874884
&mut utxo_diff,
@@ -994,6 +1004,39 @@ pub fn build_block(
9941004
}
9951005
}
9961006

1007+
for st_tx in transactions_pool.st_iter() {
1008+
let transaction_weight = st_tx.weight();
1009+
let transaction_fee = match st_transaction_fee(st_tx, &utxo_diff, epoch, epoch_constants) {
1010+
Ok(x) => x,
1011+
Err(e) => {
1012+
log::warn!(
1013+
"Error when calculating transaction fee for transaction: {}",
1014+
e
1015+
);
1016+
continue;
1017+
}
1018+
};
1019+
1020+
let new_st_weight = st_weight.saturating_add(transaction_weight);
1021+
if new_st_weight <= max_st_weight {
1022+
update_utxo_diff(
1023+
&mut utxo_diff,
1024+
st_tx.body.inputs.iter(),
1025+
st_tx.body.change.iter(),
1026+
st_tx.hash(),
1027+
);
1028+
stake_txns.push(st_tx.clone());
1029+
transaction_fees = transaction_fees.saturating_add(transaction_fee);
1030+
st_weight = new_st_weight;
1031+
}
1032+
1033+
// The condition to stop is if the free space in the block for VTTransactions
1034+
// is less than the minimum stake transaction weight
1035+
if st_weight > max_st_weight.saturating_sub(min_st_weight) {
1036+
break;
1037+
}
1038+
}
1039+
9971040
// Include Mint Transaction by miner
9981041
let reward = block_reward(epoch, initial_block_reward, halving_period) + transaction_fees;
9991042
let mint = MintTransaction::with_external_address(
@@ -1096,6 +1139,7 @@ mod tests {
10961139
// Set `max_vt_weight` and `max_dr_weight` to zero (no transaction should be included)
10971140
let max_vt_weight = 0;
10981141
let max_dr_weight = 0;
1142+
let max_st_weight = 0;
10991143

11001144
// Fields required to mine a block
11011145
let block_beacon = CheckpointBeacon::default();
@@ -1109,6 +1153,7 @@ mod tests {
11091153
(&mut transaction_pool, &unspent_outputs_pool, &dr_pool),
11101154
max_vt_weight,
11111155
max_dr_weight,
1156+
max_st_weight,
11121157
block_beacon,
11131158
block_proof,
11141159
&[],
@@ -1277,6 +1322,7 @@ mod tests {
12771322
// Set `max_vt_weight` to fit only `transaction_1` weight
12781323
let max_vt_weight = vt_tx1.weight();
12791324
let max_dr_weight = 0;
1325+
let max_st_weight = 0;
12801326

12811327
// Insert transactions into `transactions_pool`
12821328
let mut transaction_pool = TransactionsPool::default();
@@ -1313,6 +1359,7 @@ mod tests {
13131359
(&mut transaction_pool, &unspent_outputs_pool, &dr_pool),
13141360
max_vt_weight,
13151361
max_dr_weight,
1362+
max_st_weight,
13161363
block_beacon,
13171364
block_proof,
13181365
&[],
@@ -1378,6 +1425,7 @@ mod tests {
13781425
// Set `max_vt_weight` to fit only 1 transaction weight
13791426
let max_vt_weight = vt_tx2.weight();
13801427
let max_dr_weight = 0;
1428+
let max_st_weight = 0;
13811429

13821430
// Insert transactions into `transactions_pool`
13831431
let mut transaction_pool = TransactionsPool::default();
@@ -1414,6 +1462,7 @@ mod tests {
14141462
(&mut transaction_pool, &unspent_outputs_pool, &dr_pool),
14151463
max_vt_weight,
14161464
max_dr_weight,
1465+
max_st_weight,
14171466
block_beacon,
14181467
block_proof,
14191468
&[],
@@ -1493,6 +1542,7 @@ mod tests {
14931542
// Set `max_vt_weight` to fit only `transaction_1` weight
14941543
let max_vt_weight = 0;
14951544
let max_dr_weight = dr_tx1.weight();
1545+
let max_st_weight = 0;
14961546

14971547
// Insert transactions into `transactions_pool`
14981548
let mut transaction_pool = TransactionsPool::default();
@@ -1529,6 +1579,7 @@ mod tests {
15291579
(&mut transaction_pool, &unspent_outputs_pool, &dr_pool),
15301580
max_vt_weight,
15311581
max_dr_weight,
1582+
max_st_weight,
15321583
block_beacon,
15331584
block_proof,
15341585
&[],
@@ -1591,6 +1642,7 @@ mod tests {
15911642
// Set `max_vt_weight` to fit only `transaction_1` weight
15921643
let max_vt_weight = 0;
15931644
let max_dr_weight = dr_tx2.weight();
1645+
let max_st_weight = 0;
15941646

15951647
// Insert transactions into `transactions_pool`
15961648
let mut transaction_pool = TransactionsPool::default();
@@ -1627,6 +1679,7 @@ mod tests {
16271679
(&mut transaction_pool, &unspent_outputs_pool, &dr_pool),
16281680
max_vt_weight,
16291681
max_dr_weight,
1682+
max_st_weight,
16301683
block_beacon,
16311684
block_proof,
16321685
&[],

node/src/actors/inventory_manager/handlers.rs

+2
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,7 @@ mod tests {
447447
// Set `max_vt_weight` to fit only `transaction_1` weight
448448
let max_vt_weight = vt_tx1.weight();
449449
let max_dr_weight = 0;
450+
let max_st_weight = 0;
450451

451452
// Insert transactions into `transactions_pool`
452453
let mut transaction_pool = TransactionsPool::default();
@@ -480,6 +481,7 @@ mod tests {
480481
(&mut transaction_pool, &unspent_outputs_pool, &dr_pool),
481482
max_vt_weight,
482483
max_dr_weight,
484+
max_st_weight,
483485
block_beacon,
484486
block_proof,
485487
&[],

0 commit comments

Comments
 (0)