Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix the tracking of txs coming from other wallets #1828

Merged
merged 1 commit into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions wallet/src/account/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ use common::address::{Address, RpcAddress};
use common::chain::output_value::{OutputValue, RpcOutputValue};
use common::chain::tokens::{
make_token_id, IsTokenUnfreezable, NftIssuance, NftIssuanceV0, RPCFungibleTokenInfo, TokenId,
TokenIssuance,
};
use common::chain::{
AccountNonce, Block, ChainConfig, DelegationId, Destination, GenBlock, PoolId,
Expand Down Expand Up @@ -1697,11 +1698,17 @@ impl Account {
vec![data.decommission_key().clone(), data.staker().clone()]
}
TxOutput::Htlc(_, htlc) => vec![htlc.spend_key.clone(), htlc.refund_key.clone()],
TxOutput::IssueFungibleToken(_)
| TxOutput::Burn(_)
| TxOutput::DelegateStaking(_, _)
| TxOutput::DataDeposit(_)
| TxOutput::CreateOrder(_) => Vec::new(),
TxOutput::IssueFungibleToken(data) => match data.as_ref() {
TokenIssuance::V1(data) => vec![data.authority.clone()],
},
TxOutput::DelegateStaking(_, delegation_id) => self
.output_cache
.delegation_data(delegation_id)
.map_or(vec![], |data| vec![data.destination.clone()]),
TxOutput::CreateOrder(data) => {
vec![data.conclude_key().clone()]
}
TxOutput::Burn(_) | TxOutput::DataDeposit(_) => Vec::new(),
}
}

Expand Down
196 changes: 171 additions & 25 deletions wallet/src/wallet/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1675,39 +1675,119 @@ fn send_to_unknown_delegation(#[case] seed: Seed) {
let mut rng = make_seedable_rng(seed);
let chain_config = Arc::new(create_mainnet());

let mut wallet = create_wallet(chain_config.clone());
let mut wallet = create_wallet_with_mnemonic(chain_config.clone(), MNEMONIC);
let mut wallet2 = create_wallet_with_mnemonic(chain_config.clone(), MNEMONIC2);

let coin_balance = get_coin_balance(&wallet);
assert_eq!(coin_balance, Amount::ZERO);

// Generate a new block which sends reward to the wallet
let delegation_amount = Amount::from_atoms(rng.gen_range(2..100));
let block1_amount = delegation_amount;
let _ = create_block(&chain_config, &mut wallet, vec![], block1_amount, 0);
let block_height = 0;
let (_, block) = create_block(
&chain_config,
&mut wallet,
vec![],
block1_amount,
block_height,
);

scan_wallet(
&mut wallet2,
BlockHeight::new(block_height),
vec![block.clone()],
);

let coin_balance = get_coin_balance(&wallet);
assert_eq!(coin_balance, delegation_amount);
let coin_balance = get_coin_balance(&wallet2);
assert_eq!(coin_balance, Amount::ZERO);

let unknown_delegation_id = DelegationId::new(H256::zero());
let block_height = 1;
let (_, block) = create_block(
&chain_config,
&mut wallet2,
vec![],
block1_amount,
block_height,
);

scan_wallet(
&mut wallet,
BlockHeight::new(block_height),
vec![block.clone()],
);

let coin_balance = get_coin_balance(&wallet);
assert_eq!(coin_balance, delegation_amount);
let coin_balance = get_coin_balance(&wallet2);
assert_eq!(coin_balance, delegation_amount);

let unknown_pool_id = PoolId::new(H256::zero());
let address2 = wallet2.get_new_address(DEFAULT_ACCOUNT_INDEX).unwrap().1;
let (wallet2_delegation_id, delegation_tx) = wallet2
.create_delegation(
DEFAULT_ACCOUNT_INDEX,
vec![make_create_delegation_output(address2.clone(), unknown_pool_id)],
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
)
.unwrap();

let block_height = 2;
let (_, block) = create_block(
&chain_config,
&mut wallet,
vec![delegation_tx],
Amount::ZERO,
block_height,
);
scan_wallet(
&mut wallet2,
BlockHeight::new(block_height),
vec![block.clone()],
);

let delegation_data =
wallet2.get_delegation(DEFAULT_ACCOUNT_INDEX, wallet2_delegation_id).unwrap();
assert_eq!(delegation_data.pool_id, unknown_pool_id);
assert_eq!(&delegation_data.destination, address2.as_object());
assert!(delegation_data.not_staked_yet);

// Stake from wallet1 to wallet2's delegation
let delegation_stake_tx = wallet
.create_transaction_to_addresses(
DEFAULT_ACCOUNT_INDEX,
[TxOutput::DelegateStaking(delegation_amount, unknown_delegation_id)],
[TxOutput::DelegateStaking(delegation_amount, wallet2_delegation_id)],
SelectedInputs::Utxos(vec![]),
BTreeMap::new(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
)
.unwrap();

let _ = create_block(
let block_height = 3;
let (_, block) = create_block(
&chain_config,
&mut wallet,
vec![delegation_stake_tx],
block1_amount,
1,
block_height,
);
scan_wallet(
&mut wallet2,
BlockHeight::new(block_height),
vec![block.clone()],
);

// Wallet2 should see the transaction and know that someone has staked to the delegation
let delegation_data =
wallet2.get_delegation(DEFAULT_ACCOUNT_INDEX, wallet2_delegation_id).unwrap();
assert_eq!(delegation_data.pool_id, unknown_pool_id);
assert_eq!(&delegation_data.destination, address2.as_object());
assert!(!delegation_data.not_staked_yet);

let coin_balance = get_coin_balance(&wallet);
assert_eq!(coin_balance, block1_amount);

Expand Down Expand Up @@ -1984,7 +2064,8 @@ fn issue_and_transfer_tokens(#[case] seed: Seed) {
let mut rng = make_seedable_rng(seed);
let chain_config = Arc::new(create_mainnet());

let mut wallet = create_wallet(chain_config.clone());
let mut wallet = create_wallet_with_mnemonic(chain_config.clone(), MNEMONIC);
let mut wallet2 = create_wallet_with_mnemonic(chain_config.clone(), MNEMONIC2);

let coin_balance = get_coin_balance(&wallet);
assert_eq!(coin_balance, Amount::ZERO);
Expand All @@ -1998,36 +2079,53 @@ fn issue_and_transfer_tokens(#[case] seed: Seed) {
chain_config.nft_issuance_fee(BlockHeight::zero())
};

// Generate a new block which sends reward to the wallet
let mut block1_amount =
(Amount::from_atoms(rng.gen_range(NETWORK_FEE + 100..NETWORK_FEE + 10000)) + issuance_fee)
.unwrap();
let some_coins = 100;
// Generate a new block which sends reward to the wallet2
let mut block1_amount = (Amount::from_atoms(
rng.gen_range(NETWORK_FEE + some_coins..NETWORK_FEE + some_coins * 100),
) + issuance_fee)
.unwrap();

if issue_fungible_token {
block1_amount =
(block1_amount + chain_config.token_supply_change_fee(BlockHeight::zero())).unwrap();
}

let _ = create_block(&chain_config, &mut wallet, vec![], block1_amount, 0);
let token_authority_and_destination = wallet.get_new_address(DEFAULT_ACCOUNT_INDEX).unwrap().1;

let coin_balance = get_coin_balance(&wallet);
assert_eq!(coin_balance, block1_amount);
// Issue token randomly from wallet2 to wallet1 or wallet1 to wallet1
let (random_issuing_wallet, other_wallet) = if rng.gen::<bool>() {
(&mut wallet, &mut wallet2)
} else {
(&mut wallet2, &mut wallet)
};

let address2 = wallet.get_new_address(DEFAULT_ACCOUNT_INDEX).unwrap().1;
let (_, block) = create_block(
&chain_config,
random_issuing_wallet,
vec![],
block1_amount,
0,
);
scan_wallet(other_wallet, BlockHeight::new(0), vec![block.clone()]);

let coin_balance = get_coin_balance(random_issuing_wallet);
assert_eq!(coin_balance, block1_amount);

let amount_fraction = (block1_amount.into_atoms() - NETWORK_FEE) / 10;
let mut token_amount_to_issue = Amount::from_atoms(rng.gen_range(1..amount_fraction));

let (issued_token_id, token_issuance_transaction) = if issue_fungible_token {
let (issued_token_id, token_issuance_transactions) = if issue_fungible_token {
let token_issuance = TokenIssuanceV1 {
token_ticker: "XXXX".as_bytes().to_vec(),
number_of_decimals: rng.gen_range(1..18),
metadata_uri: "http://uri".as_bytes().to_vec(),
total_supply: common::chain::tokens::TokenTotalSupply::Unlimited,
authority: address2.as_object().clone(),
authority: token_authority_and_destination.as_object().clone(),
is_freezable: common::chain::tokens::IsTokenFreezable::No,
};
let (issued_token_id, token_issuance_transaction) = wallet
// issue a new token from a random wallet 1 or 2 to a destination from wallet1
let (issued_token_id, token_issuance_transaction) = random_issuing_wallet
.issue_new_token(
DEFAULT_ACCOUNT_INDEX,
TokenIssuance::V1(token_issuance.clone()),
Expand All @@ -2049,37 +2147,68 @@ fn issue_and_transfer_tokens(#[case] seed: Seed) {
token_issuance.authority,
);

wallet
random_issuing_wallet
.add_account_unconfirmed_tx(
DEFAULT_ACCOUNT_INDEX,
token_issuance_transaction.clone(),
&WalletEventsNoOp,
)
.unwrap();
other_wallet
.add_account_unconfirmed_tx(
DEFAULT_ACCOUNT_INDEX,
token_issuance_transaction.clone(),
&WalletEventsNoOp,
)
.unwrap();

// transfer the remaining coins from the random wallet to wallet1 so it can continue with
// other transactions
let transfer_tx = random_issuing_wallet
.create_transaction_to_addresses(
DEFAULT_ACCOUNT_INDEX,
[TxOutput::Transfer(
OutputValue::Coin((block1_amount - issuance_fee).unwrap()),
token_authority_and_destination.as_object().clone(),
)],
SelectedInputs::Utxos(vec![]),
BTreeMap::new(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
)
.unwrap();
wallet
.add_account_unconfirmed_tx(
DEFAULT_ACCOUNT_INDEX,
transfer_tx.clone(),
&WalletEventsNoOp,
)
.unwrap();

// wallet1 should know about the issued token from the random wallet
let unconfirmed_token_info =
wallet.get_token_unconfirmed_info(DEFAULT_ACCOUNT_INDEX, &token_info).unwrap();
let mint_transaction = wallet
.mint_tokens(
DEFAULT_ACCOUNT_INDEX,
&unconfirmed_token_info,
token_amount_to_issue,
address2,
token_authority_and_destination,
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
)
.unwrap();

(
issued_token_id,
vec![token_issuance_transaction, mint_transaction],
vec![token_issuance_transaction, transfer_tx, mint_transaction],
)
} else {
token_amount_to_issue = Amount::from_atoms(1);
let (issued_token_id, token_issuance_transaction) = wallet
let (issued_token_id, nft_issuance_transaction) = random_issuing_wallet
.issue_new_nft(
DEFAULT_ACCOUNT_INDEX,
address2,
token_authority_and_destination.clone(),
Metadata {
creator: None,
name: "Name".as_bytes().to_vec(),
Expand All @@ -2094,13 +2223,30 @@ fn issue_and_transfer_tokens(#[case] seed: Seed) {
FeeRate::from_amount_per_kb(Amount::ZERO),
)
.unwrap();
(issued_token_id, vec![token_issuance_transaction])
random_issuing_wallet
.add_unconfirmed_tx(nft_issuance_transaction.clone(), &WalletEventsNoOp)
.unwrap();

let transfer_tx = random_issuing_wallet
.create_transaction_to_addresses(
DEFAULT_ACCOUNT_INDEX,
[TxOutput::Transfer(
OutputValue::Coin((block1_amount - issuance_fee).unwrap()),
token_authority_and_destination.as_object().clone(),
)],
SelectedInputs::Utxos(vec![]),
BTreeMap::new(),
FeeRate::from_amount_per_kb(Amount::ZERO),
FeeRate::from_amount_per_kb(Amount::ZERO),
)
.unwrap();
(issued_token_id, vec![nft_issuance_transaction, transfer_tx])
};

let _ = create_block(
&chain_config,
&mut wallet,
token_issuance_transaction,
token_issuance_transactions,
block1_amount,
1,
);
Expand Down
Loading