Skip to content

Commit

Permalink
Merge pull request #1782 from mintlayer:fix/accounting_view_on_reorg
Browse files Browse the repository at this point in the history
Fix accounting view on reorg
  • Loading branch information
TheQuantumPhysicist authored Jun 17, 2024
2 parents f246c4f + 107fafc commit 37466b7
Show file tree
Hide file tree
Showing 19 changed files with 731 additions and 75 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions chainstate/src/detail/ban_score.rs
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ impl BanScore for pos_accounting::Error {
E::DelegationDeletionFailedBalanceNonZero => 100,
E::DelegationDeletionFailedPoolsShareNonZero => 100,
E::DelegationDeletionFailedPoolStillExists => 100,
E::InvariantErrorNonZeroBalanceForNonExistingDelegation => 100,
}
}
}
Expand Down Expand Up @@ -568,6 +569,7 @@ impl BanScore for tokens_accounting::Error {
tokens_accounting::Error::CannotLockFrozenToken(_) => 100,
tokens_accounting::Error::CannotChangeAuthorityForFrozenToken(_) => 100,
tokens_accounting::Error::CannotUndoChangeAuthorityForFrozenToken(_) => 100,
tokens_accounting::Error::InvariantErrorNonZeroSupplyForNonExistingToken => 100,
tokens_accounting::Error::ViewFail => 0,
tokens_accounting::Error::StorageWrite => 0,
}
Expand Down
6 changes: 4 additions & 2 deletions chainstate/src/detail/error_classification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,8 @@ impl BlockProcessingErrorClassification for tokens_accounting::Error {
| Error::CannotUndoFreezeTokenThatIsNotFrozen(_)
| Error::CannotUndoUnfreezeTokenThatIsFrozen(_)
| Error::CannotChangeAuthorityForFrozenToken(_)
| Error::CannotUndoChangeAuthorityForFrozenToken(_) => {
| Error::CannotUndoChangeAuthorityForFrozenToken(_)
| Error::InvariantErrorNonZeroSupplyForNonExistingToken => {
BlockProcessingErrorClass::BadBlock
}

Expand Down Expand Up @@ -775,7 +776,8 @@ impl BlockProcessingErrorClassification for pos_accounting::Error {
| Error::IncreaseStakerRewardsOfNonexistingPool
| Error::StakerBalanceOverflow
| Error::InvariantErrorIncreasePledgeUndoFailedPoolBalanceNotFound
| Error::InvariantErrorIncreaseStakerRewardUndoFailedPoolBalanceNotFound => {
| Error::InvariantErrorIncreaseStakerRewardUndoFailedPoolBalanceNotFound
| Error::InvariantErrorNonZeroBalanceForNonExistingDelegation => {
BlockProcessingErrorClass::BadBlock
}

Expand Down
2 changes: 2 additions & 0 deletions chainstate/test-framework/src/key_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ use common::{
use crypto::key::{KeyKind, PrivateKey, PublicKey};
use randomness::{CryptoRng, Rng};

#[derive(Clone)]
struct Multisig {
keys: Vec<(PrivateKey, PublicKey)>,
min_required_signatures: NonZeroU8,
Expand All @@ -53,6 +54,7 @@ impl Multisig {
}
}

#[derive(Clone)]
pub struct KeyManager {
public_key_hashes: BTreeMap<PublicKeyHash, PrivateKey>,
public_keys: BTreeMap<PublicKey, PrivateKey>,
Expand Down
1 change: 1 addition & 0 deletions chainstate/test-framework/src/transaction_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use common::{
use rstest::rstest;

/// The transaction builder.
#[derive(Clone)]
pub struct TransactionBuilder {
flags: u128,
inputs: Vec<TxInput>,
Expand Down
160 changes: 160 additions & 0 deletions chainstate/test-suite/src/tests/fungible_tokens_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5329,3 +5329,163 @@ fn reorg_tokens_tx_with_simple_tx(#[case] seed: Seed) {
let new_chain_block_id = tf.create_chain(&tf.genesis().get_id().into(), 2, &mut rng).unwrap();
assert_eq!(new_chain_block_id, tf.best_block_id());
}

#[rstest]
#[trace]
#[case(Seed::from_entropy())]
fn issue_same_token_alternative_pos_chain(#[case] seed: Seed) {
use chainstate_test_framework::create_stake_pool_data_with_all_reward_to_staker;
use common::{
chain::{config::create_unit_test_config, PoolId},
primitives::H256,
};
use crypto::vrf::{VRFKeyKind, VRFPrivateKey};

utils::concurrency::model(move || {
let mut rng = make_seedable_rng(seed);
let (vrf_sk, vrf_pk) = VRFPrivateKey::new_from_rng(&mut rng, VRFKeyKind::Schnorrkel);

let genesis_pool_id = PoolId::new(H256::random_using(&mut rng));
let amount_to_stake = create_unit_test_config().min_stake_pool_pledge();

let (stake_pool_data, staking_sk) = create_stake_pool_data_with_all_reward_to_staker(
&mut rng,
amount_to_stake,
vrf_pk.clone(),
);

let chain_config = chainstate_test_framework::create_chain_config_with_staking_pool(
&mut rng,
(amount_to_stake * 2).unwrap(),
genesis_pool_id,
stake_pool_data,
)
.build();
let target_block_time = chain_config.target_block_spacing();
let mut tf = TestFramework::builder(&mut rng).with_chain_config(chain_config).build();
tf.progress_time_seconds_since_epoch(target_block_time.as_secs());

let genesis_block_id = tf.genesis().get_id();
let token_supply_change_fee =
tf.chainstate.get_chain_config().token_supply_change_fee(BlockHeight::zero());

//issue a token
let issuance = make_issuance(
&mut rng,
TokenTotalSupply::Fixed(Amount::from_atoms(100)),
IsTokenFreezable::No,
);
let issue_token_tx = TransactionBuilder::new()
.add_input(
TxInput::from_utxo(genesis_block_id.into(), 0),
InputWitness::NoSignature(None),
)
.add_output(TxOutput::Transfer(
OutputValue::Coin(token_supply_change_fee),
Destination::AnyoneCanSpend,
))
.add_output(TxOutput::IssueFungibleToken(Box::new(issuance.clone())))
.build();
let token_id = make_token_id(issue_token_tx.transaction().inputs()).unwrap();
let tx_id = issue_token_tx.transaction().get_id();
tf.make_pos_block_builder()
.with_stake_pool_id(genesis_pool_id)
.with_stake_spending_key(staking_sk.clone())
.with_vrf_key(vrf_sk.clone())
.add_transaction(issue_token_tx)
.build_and_process(&mut rng)
.unwrap();

// Mint some tokens to increase circulating supply
let mint_block_index = tf
.make_pos_block_builder()
.with_stake_pool_id(genesis_pool_id)
.with_stake_spending_key(staking_sk.clone())
.with_vrf_key(vrf_sk.clone())
.add_transaction(
TransactionBuilder::new()
.add_input(
TxInput::from_command(
AccountNonce::new(0),
AccountCommand::MintTokens(token_id, Amount::from_atoms(5)),
),
InputWitness::NoSignature(None),
)
.add_input(
UtxoOutPoint::new(tx_id.into(), 0).into(),
InputWitness::NoSignature(None),
)
.add_output(TxOutput::Transfer(
OutputValue::TokenV1(token_id, Amount::from_atoms(5)),
Destination::AnyoneCanSpend,
))
.build(),
)
.build_and_process(&mut rng)
.unwrap()
.unwrap();
assert_eq!(
Id::<GenBlock>::from(*mint_block_index.block_id()),
tf.best_block_id()
);

// issue same token in alternative chain
let alt_block_a = tf
.make_pos_block_builder()
.with_parent(genesis_block_id.into())
.with_stake_pool_id(genesis_pool_id)
.with_stake_spending_key(staking_sk.clone())
.with_vrf_key(vrf_sk.clone())
.add_transaction(
TransactionBuilder::new()
.add_input(
TxInput::from_utxo(genesis_block_id.into(), 0),
InputWitness::NoSignature(None),
)
.add_output(TxOutput::Transfer(
OutputValue::Coin((token_supply_change_fee * 2).unwrap()),
Destination::AnyoneCanSpend,
))
.add_output(TxOutput::IssueFungibleToken(Box::new(issuance)))
.build(),
)
.build(&mut rng);
let alt_block_a_id = alt_block_a.get_id();
tf.process_block(alt_block_a, BlockSource::Local).unwrap();

assert_ne!(Id::<GenBlock>::from(alt_block_a_id), tf.best_block_id());
assert_eq!(
Id::<GenBlock>::from(*mint_block_index.block_id()),
tf.best_block_id()
);

let alt_block_b = tf
.make_pos_block_builder()
.with_parent(alt_block_a_id.into())
.with_stake_pool_id(genesis_pool_id)
.with_stake_spending_key(staking_sk.clone())
.with_vrf_key(vrf_sk.clone())
.build(&mut rng);
let alt_block_b_id = alt_block_b.get_id();
tf.process_block(alt_block_b, BlockSource::Local).unwrap();

assert_ne!(Id::<GenBlock>::from(alt_block_b_id), tf.best_block_id());
assert_eq!(
Id::<GenBlock>::from(*mint_block_index.block_id()),
tf.best_block_id()
);

// Trigger a reorg
let alt_block_c = tf
.make_pos_block_builder()
.with_parent(alt_block_b_id.into())
.with_stake_pool_id(genesis_pool_id)
.with_stake_spending_key(staking_sk.clone())
.with_vrf_key(vrf_sk.clone())
.build(&mut rng);
let alt_block_c_id = alt_block_c.get_id();
tf.process_block(alt_block_c, BlockSource::Local).unwrap();

assert_eq!(Id::<GenBlock>::from(alt_block_c_id), tf.best_block_id());
});
}
Loading

0 comments on commit 37466b7

Please sign in to comment.