Skip to content

Commit b178e6a

Browse files
committed
Forbid changing staker's destination in ProduceBlockFromStake after a fork
1 parent 2729c09 commit b178e6a

File tree

51 files changed

+885
-388
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+885
-388
lines changed

Cargo.lock

Lines changed: 17 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api-server/stack-test-suite/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ api-web-server = { path = "../web-server" }
1212
chainstate = { path = "../../chainstate" }
1313
chainstate-test-framework = { path = "../../chainstate/test-framework" }
1414
common = { path = "../../common" }
15+
common-test-helpers = { path = "../../common/test-helpers" }
1516
crypto = { path = "../../crypto" }
1617
randomness = { path = "../../randomness" }
1718
serialization = { path = "../../serialization" }

api-server/stack-test-suite/tests/v2/orders.rs

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use common::chain::{
1717
make_order_id, AccountCommand, AccountNonce, OrderAccountCommand, OrderData, OrdersVersion,
1818
};
19+
use common_test_helpers::chainstate_upgrade_builder::ChainstateUpgradeBuilder;
1920

2021
use super::*;
2122

@@ -41,17 +42,7 @@ async fn create_fill_conclude_order(#[case] seed: Seed, #[case] version: OrdersV
4142
.chainstate_upgrades(
4243
common::chain::NetUpgrades::initialize(vec![(
4344
BlockHeight::zero(),
44-
common::chain::ChainstateUpgrade::new(
45-
common::chain::TokenIssuanceVersion::V1,
46-
common::chain::RewardDistributionVersion::V1,
47-
common::chain::TokensFeeVersion::V1,
48-
common::chain::DataDepositFeeVersion::V1,
49-
common::chain::ChangeTokenMetadataUriActivated::Yes,
50-
common::chain::FrozenTokensValidationVersion::V1,
51-
common::chain::HtlcActivated::Yes,
52-
common::chain::OrdersActivated::Yes,
53-
version,
54-
),
45+
ChainstateUpgradeBuilder::latest().orders_version(version).build(),
5546
)])
5647
.expect("cannot fail"),
5748
)

chainstate/constraints-value-accumulator/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ thiserror.workspace = true
2121

2222
[dev-dependencies]
2323
accounting = { path = "../../accounting" }
24+
common-test-helpers = { path = "../../common/test-helpers" }
2425
test-utils = { path = "../../test-utils" }
2526

2627
rstest.workspace = true

chainstate/constraints-value-accumulator/src/tests/orders_constraints.rs

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
use std::collections::BTreeMap;
1717

18+
use rstest::rstest;
19+
1820
use common::{
1921
chain::{
2022
config::{create_unit_test_config, create_unit_test_config_builder},
@@ -25,10 +27,10 @@ use common::{
2527
},
2628
primitives::{Amount, BlockHeight, CoinOrTokenId, Fee, Id, H256},
2729
};
30+
use common_test_helpers::chainstate_upgrade_builder::ChainstateUpgradeBuilder;
2831
use orders_accounting::{InMemoryOrdersAccounting, OrdersAccountingDB};
2932
use pos_accounting::{InMemoryPoSAccounting, PoSAccountingDB};
3033
use randomness::Rng;
31-
use rstest::rstest;
3234
use test_utils::random::{make_seedable_rng, Seed};
3335

3436
use crate::{ConstrainedValueAccumulator, Error};
@@ -264,17 +266,7 @@ fn fill_order_constraints(#[case] seed: Seed, #[case] version: OrdersVersion) {
264266
.chainstate_upgrades(
265267
common::chain::NetUpgrades::initialize(vec![(
266268
BlockHeight::zero(),
267-
common::chain::ChainstateUpgrade::new(
268-
common::chain::TokenIssuanceVersion::V1,
269-
common::chain::RewardDistributionVersion::V1,
270-
common::chain::TokensFeeVersion::V1,
271-
common::chain::DataDepositFeeVersion::V1,
272-
common::chain::ChangeTokenMetadataUriActivated::Yes,
273-
common::chain::FrozenTokensValidationVersion::V1,
274-
common::chain::HtlcActivated::Yes,
275-
common::chain::OrdersActivated::Yes,
276-
version,
277-
),
269+
ChainstateUpgradeBuilder::latest().orders_version(version).build(),
278270
)])
279271
.expect("cannot fail"),
280272
)
@@ -639,17 +631,7 @@ fn conclude_order_constraints(#[case] seed: Seed, #[case] version: OrdersVersion
639631
.chainstate_upgrades(
640632
common::chain::NetUpgrades::initialize(vec![(
641633
BlockHeight::zero(),
642-
common::chain::ChainstateUpgrade::new(
643-
common::chain::TokenIssuanceVersion::V1,
644-
common::chain::RewardDistributionVersion::V1,
645-
common::chain::TokensFeeVersion::V1,
646-
common::chain::DataDepositFeeVersion::V1,
647-
common::chain::ChangeTokenMetadataUriActivated::Yes,
648-
common::chain::FrozenTokensValidationVersion::V1,
649-
common::chain::HtlcActivated::Yes,
650-
common::chain::OrdersActivated::Yes,
651-
version,
652-
),
634+
ChainstateUpgradeBuilder::latest().orders_version(version).build(),
653635
)])
654636
.expect("cannot fail"),
655637
)

chainstate/src/detail/ban_score.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ impl BanScore for ConnectTransactionError {
144144
ConnectTransactionError::OrdersAccountingError(err) => err.ban_score(),
145145
ConnectTransactionError::AttemptToCreateOrderFromAccounts => 100,
146146
ConnectTransactionError::ConcludeInputAmountsDontMatch(_, _) => 100,
147+
ConnectTransactionError::ProduceBlockFromStakeChangesStakerDestination(_, _) => 100,
147148
}
148149
}
149150
}
@@ -454,6 +455,7 @@ impl BanScore for ConsensusPoSError {
454455
ConsensusPoSError::EffectivePoolBalanceError(_) => 100,
455456
ConsensusPoSError::EmptyTimespan => 100,
456457
ConsensusPoSError::FailedToCalculateCappedBalance => 100,
458+
ConsensusPoSError::InvalidOutputTypeInStakeKernel(_) => 100,
457459
}
458460
}
459461
}
@@ -462,7 +464,6 @@ impl BanScore for BlockSignatureError {
462464
fn ban_score(&self) -> u32 {
463465
match self {
464466
BlockSignatureError::BlockSignatureNotFound(_) => 100,
465-
BlockSignatureError::WrongOutputType(_) => 100,
466467
BlockSignatureError::WrongDestination(_) => 100,
467468
BlockSignatureError::BadSignature(_) => 100,
468469
}

chainstate/src/detail/error_classification.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,8 @@ impl BlockProcessingErrorClassification for ConnectTransactionError {
302302
| ConnectTransactionError::TotalFeeRequiredOverflow
303303
| ConnectTransactionError::InsufficientCoinsFee(_, _)
304304
| ConnectTransactionError::AttemptToSpendFrozenToken(_)
305-
| ConnectTransactionError::ConcludeInputAmountsDontMatch(_, _) => {
305+
| ConnectTransactionError::ConcludeInputAmountsDontMatch(_, _)
306+
| ConnectTransactionError::ProduceBlockFromStakeChangesStakerDestination(_, _) => {
306307
BlockProcessingErrorClass::BadBlock
307308
}
308309

@@ -643,7 +644,8 @@ impl BlockProcessingErrorClassification for ConsensusPoSError {
643644
| ConsensusPoSError::PoSBlockTimeStrictOrderInvalid(_)
644645
| ConsensusPoSError::FiniteTotalSupplyIsRequired
645646
| ConsensusPoSError::UnsupportedConsensusVersion
646-
| ConsensusPoSError::FailedToCalculateCappedBalance => {
647+
| ConsensusPoSError::FailedToCalculateCappedBalance
648+
| ConsensusPoSError::InvalidOutputTypeInStakeKernel(_) => {
647649
BlockProcessingErrorClass::BadBlock
648650
}
649651

chainstate/test-framework/src/framework.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ use crate::{
3333
BlockBuilder, TestChainstate, TestFrameworkBuilder, TestStore,
3434
};
3535
use chainstate::{chainstate_interface::ChainstateInterface, BlockSource, ChainstateError};
36-
use chainstate_types::{BlockIndex, BlockStatus, GenBlockIndex};
36+
use chainstate_types::{
37+
pos_randomness::PoSRandomness, BlockIndex, BlockStatus, EpochStorageRead as _, GenBlockIndex,
38+
};
3739
use common::{
3840
chain::{
3941
Block, ChainConfig, GenBlock, GenBlockId, Genesis, OutPointSourceId, PoolId, TxOutput,
@@ -557,6 +559,22 @@ impl TestFramework {
557559
.unwrap();
558560
self.on_pool_created(*pool_id, staker_key, vrf_sk, outpoint);
559561
}
562+
563+
pub fn pos_randomness_for_height(&self, height: &BlockHeight) -> PoSRandomness {
564+
let chain_config = self.chain_config();
565+
566+
chain_config
567+
.sealed_epoch_index(height)
568+
.and_then(|epoch_index| {
569+
self.storage
570+
.transaction_ro()
571+
.unwrap()
572+
.get_epoch_data(epoch_index)
573+
.unwrap()
574+
.map(|epoch_data| *epoch_data.randomness())
575+
})
576+
.unwrap_or(PoSRandomness::new(chain_config.initial_randomness()))
577+
}
560578
}
561579

562580
#[rstest]

chainstate/test-framework/src/pos_block_builder.rs

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use crate::{
2323
};
2424
use chainstate::{BlockSource, ChainstateError};
2525
use chainstate_storage::{BlockchainStorageRead, Transactional};
26-
use chainstate_types::{pos_randomness::PoSRandomness, BlockIndex, EpochStorageRead};
26+
use chainstate_types::{pos_randomness::PoSRandomness, BlockIndex};
2727
use common::{
2828
chain::{
2929
block::{
@@ -342,20 +342,9 @@ impl<'f> PoSBlockBuilder<'f> {
342342
let chain_config = self.framework.chainstate.get_chain_config().as_ref();
343343
let epoch_index = chain_config.epoch_index_from_height(&new_block_height);
344344

345-
let randomness = self.randomness.unwrap_or_else(|| {
346-
match chain_config.sealed_epoch_index(&new_block_height) {
347-
Some(epoch) => *self
348-
.framework
349-
.storage
350-
.transaction_ro()
351-
.unwrap()
352-
.get_epoch_data(epoch)
353-
.unwrap()
354-
.unwrap()
355-
.randomness(),
356-
None => PoSRandomness::new(chain_config.initial_randomness()),
357-
}
358-
});
345+
let randomness = self
346+
.randomness
347+
.unwrap_or_else(|| self.framework.pos_randomness_for_height(&new_block_height));
359348

360349
pos_mine(
361350
rng,

chainstate/test-suite/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@ hex.workspace = true
3333
itertools.workspace = true
3434

3535
[dev-dependencies]
36+
common-test-helpers = { path = "../../common/test-helpers" }
37+
tokio = { workspace = true, features = ["rt", "time"] }
38+
3639
criterion.workspace = true
3740
expect-test.workspace = true
3841
rstest.workspace = true
39-
tokio = { workspace = true, features = ["rt", "time"] }
4042

4143
[[bench]]
4244
name = "benches"

chainstate/test-suite/src/tests/chainstate_storage_tests.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@
1515

1616
use std::collections::BTreeMap;
1717

18-
use crate::tests::helpers::chainstate_upgrade_builder::ChainstateUpgradeBuilder;
19-
20-
use super::*;
2118
use chainstate_storage::{BlockchainStorageRead, Transactional};
2219
use chainstate_test_framework::{
2320
anyonecanspend_address, empty_witness, TestFramework, TestStore, TransactionBuilder,
@@ -31,9 +28,12 @@ use common::{
3128
},
3229
primitives::{Amount, Id, Idable},
3330
};
31+
use common_test_helpers::chainstate_upgrade_builder::ChainstateUpgradeBuilder;
3432
use test_utils::nft_utils::random_nft_issuance;
3533
use utxo::{Utxo, UtxosStorageRead, UtxosTxUndo};
3634

35+
use super::*;
36+
3737
// Process a tx with a coin. Check that new utxo and tx index are stored, best block is updated.
3838
#[rstest]
3939
#[trace]

0 commit comments

Comments
 (0)