Skip to content

Commit 677420e

Browse files
committed
add limit for unlimited txs
1 parent 5e3f1ee commit 677420e

File tree

9 files changed

+122
-19
lines changed

9 files changed

+122
-19
lines changed

contracts/satoshi-bridge/src/account.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,10 @@ impl Account {
9595
btc_pending_verify_list: HashSet::new(),
9696
}
9797
}
98+
99+
pub fn pending_sign_count(&self) -> u32 {
100+
u32::try_from(self.btc_pending_sign_ids.len()).unwrap_or(u32::MAX)
101+
}
98102
}
99103

100104
impl Contract {

contracts/satoshi-bridge/src/api/management.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -183,12 +183,12 @@ impl Contract {
183183

184184
#[payable]
185185
#[access_control_any(roles(Role::DAO))]
186-
pub fn extend_unlimited_txs_white_list(&mut self, account_ids: Vec<AccountId>) {
186+
pub fn extend_multi_txs_white_list(&mut self, account_ids: Vec<AccountId>) {
187187
assert_one_yocto();
188188
for account_id in account_ids {
189189
let is_success = self
190190
.data_mut()
191-
.unlimited_txs_white_list
191+
.multi_txs_white_list
192192
.insert(account_id.clone());
193193
require!(
194194
is_success,
@@ -199,10 +199,10 @@ impl Contract {
199199

200200
#[payable]
201201
#[access_control_any(roles(Role::DAO))]
202-
pub fn remove_unlimited_txs_white_list(&mut self, account_ids: Vec<AccountId>) {
202+
pub fn remove_multi_txs_white_list(&mut self, account_ids: Vec<AccountId>) {
203203
assert_one_yocto();
204204
for account_id in account_ids {
205-
let is_success = self.data_mut().unlimited_txs_white_list.remove(&account_id);
205+
let is_success = self.data_mut().multi_txs_white_list.remove(&account_id);
206206
require!(is_success, format!("Invalid account_id: {}", account_id));
207207
}
208208
}
@@ -475,6 +475,14 @@ impl Contract {
475475
self.internal_mut_config().max_btc_tx_pending_sec = max_btc_tx_pending_sec;
476476
}
477477

478+
#[payable]
479+
#[access_control_any(roles(Role::DAO))]
480+
pub fn set_max_pending_sign_txs(&mut self, max_pending_sign_txs: u32) {
481+
assert_one_yocto();
482+
require!(max_pending_sign_txs >= 1, "Invalid max_pending_sign_txs");
483+
self.internal_mut_config().max_pending_sign_txs = max_pending_sign_txs;
484+
}
485+
478486
#[payable]
479487
#[access_control_any(roles(Role::DAO))]
480488
pub fn set_unhealthy_utxo_amount(&mut self, unhealthy_utxo_amount: U64) {

contracts/satoshi-bridge/src/api/token_receiver.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,15 @@ impl Contract {
7777
max_gas_fee: Option<U128>,
7878
) {
7979
let (utxo_storage_keys, vutxos) = self.generate_vutxos(&mut psbt);
80-
let is_unlimited = self.data().unlimited_txs_white_list.contains(&sender_id);
80+
let max_pending = if self.data().multi_txs_white_list.contains(&sender_id) {
81+
self.internal_config().max_pending_sign_txs
82+
} else {
83+
1
84+
};
8185
let account = self.internal_unwrap_or_create_mut_account(&sender_id);
8286
require!(
83-
is_unlimited || account.btc_pending_sign_ids.is_empty(),
84-
"Previous btc tx has not been signed"
87+
account.pending_sign_count() < max_pending,
88+
"Too many pending sign transactions"
8589
);
8690

8791
let withdraw_change_address_script_pubkey =

contracts/satoshi-bridge/src/api/view.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub struct Metadata {
1717
pub relayer_white_list: Vec<AccountId>,
1818
pub extra_msg_relayer_white_list: Vec<AccountId>,
1919
pub post_action_receiver_id_white_list: Vec<AccountId>,
20-
pub unlimited_txs_white_list: Vec<AccountId>,
20+
pub multi_txs_white_list: Vec<AccountId>,
2121
#[serde(with = "u128_dec_format")]
2222
pub acc_collected_protocol_fee: u128,
2323
#[serde(with = "u128_dec_format")]
@@ -58,8 +58,8 @@ impl Contract {
5858
.iter()
5959
.cloned()
6060
.collect(),
61-
unlimited_txs_white_list: root_state
62-
.unlimited_txs_white_list
61+
multi_txs_white_list: root_state
62+
.multi_txs_white_list
6363
.iter()
6464
.cloned()
6565
.collect(),

contracts/satoshi-bridge/src/config.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ use crate::{
55

66
pub const MAX_RATIO: u32 = 10000;
77

8+
fn default_max_pending_sign_txs() -> u32 {
9+
1
10+
}
11+
812
#[near(serializers = [borsh, json])]
913
#[derive(Clone)]
1014
#[cfg_attr(not(target_arch = "wasm32"), derive(Debug))]
@@ -108,6 +112,9 @@ pub struct Config {
108112
pub max_btc_tx_pending_sec: u32,
109113
// UTXOs less than or equal to this amount are allowed to be merged through active management.
110114
pub unhealthy_utxo_amount: u64,
115+
// The maximum number of pending-sign transactions allowed per whitelisted account.
116+
#[serde(default = "default_max_pending_sign_txs")]
117+
pub max_pending_sign_txs: u32,
111118
#[cfg(feature = "zcash")]
112119
pub expiry_height_gap: u32,
113120
}

contracts/satoshi-bridge/src/legacy.rs

Lines changed: 84 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ impl From<ContractDataV0> for ContractData {
5454
extra_msg_relayer_white_list: IterableSet::new(StorageKey::ExtraMsgRelayerWhiteList),
5555
post_action_receiver_id_white_list,
5656
post_action_msg_templates: IterableMap::new(StorageKey::PostActionMsgTemplates),
57-
unlimited_txs_white_list: IterableSet::new(StorageKey::UnlimitedTxsWhiteList),
57+
multi_txs_white_list: IterableSet::new(StorageKey::MultiTxsWhiteList),
5858
lost_found,
5959
acc_collected_protocol_fee,
6060
cur_available_protocol_fee,
@@ -189,6 +189,7 @@ impl From<ConfigV0> for Config {
189189
rbf_num_limit,
190190
max_btc_tx_pending_sec,
191191
unhealthy_utxo_amount: 1000,
192+
max_pending_sign_txs: 1,
192193
#[cfg(feature = "zcash")]
193194
expiry_height_gap: 1000,
194195
}
@@ -329,6 +330,7 @@ impl From<ConfigV1> for Config {
329330
rbf_num_limit,
330331
max_btc_tx_pending_sec,
331332
unhealthy_utxo_amount,
333+
max_pending_sign_txs: 1,
332334
#[cfg(feature = "zcash")]
333335
expiry_height_gap,
334336
}
@@ -388,7 +390,7 @@ impl From<ContractDataV1> for ContractData {
388390
extra_msg_relayer_white_list: IterableSet::new(StorageKey::ExtraMsgRelayerWhiteList),
389391
post_action_receiver_id_white_list,
390392
post_action_msg_templates,
391-
unlimited_txs_white_list: IterableSet::new(StorageKey::UnlimitedTxsWhiteList),
393+
multi_txs_white_list: IterableSet::new(StorageKey::MultiTxsWhiteList),
392394
lost_found,
393395
acc_collected_protocol_fee,
394396
cur_available_protocol_fee,
@@ -463,7 +465,7 @@ impl From<ContractDataV2> for ContractData {
463465
extra_msg_relayer_white_list,
464466
post_action_receiver_id_white_list,
465467
post_action_msg_templates,
466-
unlimited_txs_white_list: IterableSet::new(StorageKey::UnlimitedTxsWhiteList),
468+
multi_txs_white_list: IterableSet::new(StorageKey::MultiTxsWhiteList),
467469
lost_found,
468470
acc_collected_protocol_fee,
469471
cur_available_protocol_fee,
@@ -474,9 +476,82 @@ impl From<ContractDataV2> for ContractData {
474476
}
475477
}
476478

479+
#[near(serializers = [borsh])]
480+
#[derive(Clone)]
481+
pub struct ConfigV2 {
482+
pub chain: crate::network::Chain,
483+
pub btc_light_client_account_id: AccountId,
484+
pub nbtc_account_id: AccountId,
485+
pub chain_signatures_account_id: AccountId,
486+
pub chain_signatures_root_public_key: Option<PublicKey>,
487+
pub change_address: Option<String>,
488+
pub confirmations_strategy: HashMap<String, u8>,
489+
pub confirmations_delta: u8,
490+
pub extra_msg_confirmations_delta: u8,
491+
pub deposit_bridge_fee: BridgeFee,
492+
pub withdraw_bridge_fee: BridgeFee,
493+
pub min_deposit_amount: u128,
494+
pub min_withdraw_amount: u128,
495+
pub min_change_amount: u128,
496+
pub max_change_amount: u128,
497+
pub min_btc_gas_fee: u128,
498+
pub max_btc_gas_fee: u128,
499+
pub max_withdrawal_input_number: u8,
500+
pub max_change_number: u8,
501+
pub max_active_utxo_management_input_number: u8,
502+
pub max_active_utxo_management_output_number: u8,
503+
pub active_management_lower_limit: u32,
504+
pub active_management_upper_limit: u32,
505+
pub passive_management_lower_limit: u32,
506+
pub passive_management_upper_limit: u32,
507+
pub rbf_num_limit: u8,
508+
pub max_btc_tx_pending_sec: u32,
509+
pub unhealthy_utxo_amount: u64,
510+
#[cfg(feature = "zcash")]
511+
pub expiry_height_gap: u32,
512+
}
513+
514+
impl From<ConfigV2> for Config {
515+
fn from(c: ConfigV2) -> Self {
516+
Self {
517+
chain: c.chain,
518+
btc_light_client_account_id: c.btc_light_client_account_id,
519+
nbtc_account_id: c.nbtc_account_id,
520+
chain_signatures_account_id: c.chain_signatures_account_id,
521+
chain_signatures_root_public_key: c.chain_signatures_root_public_key,
522+
change_address: c.change_address,
523+
confirmations_strategy: c.confirmations_strategy,
524+
confirmations_delta: c.confirmations_delta,
525+
extra_msg_confirmations_delta: c.extra_msg_confirmations_delta,
526+
deposit_bridge_fee: c.deposit_bridge_fee,
527+
withdraw_bridge_fee: c.withdraw_bridge_fee,
528+
min_deposit_amount: c.min_deposit_amount,
529+
min_withdraw_amount: c.min_withdraw_amount,
530+
min_change_amount: c.min_change_amount,
531+
max_change_amount: c.max_change_amount,
532+
min_btc_gas_fee: c.min_btc_gas_fee,
533+
max_btc_gas_fee: c.max_btc_gas_fee,
534+
max_withdrawal_input_number: c.max_withdrawal_input_number,
535+
max_change_number: c.max_change_number,
536+
max_active_utxo_management_input_number: c.max_active_utxo_management_input_number,
537+
max_active_utxo_management_output_number: c.max_active_utxo_management_output_number,
538+
active_management_lower_limit: c.active_management_lower_limit,
539+
active_management_upper_limit: c.active_management_upper_limit,
540+
passive_management_lower_limit: c.passive_management_lower_limit,
541+
passive_management_upper_limit: c.passive_management_upper_limit,
542+
rbf_num_limit: c.rbf_num_limit,
543+
max_btc_tx_pending_sec: c.max_btc_tx_pending_sec,
544+
unhealthy_utxo_amount: c.unhealthy_utxo_amount,
545+
max_pending_sign_txs: 1,
546+
#[cfg(feature = "zcash")]
547+
expiry_height_gap: c.expiry_height_gap,
548+
}
549+
}
550+
}
551+
477552
#[near(serializers = [borsh])]
478553
pub struct ContractDataV3 {
479-
pub config: LazyOption<Config>,
554+
pub config: LazyOption<ConfigV2>,
480555
pub accounts: IterableMap<AccountId, VAccount>,
481556
pub utxos: IterableMap<String, VUTXO>,
482557
pub unavailable_utxos: IterableMap<String, VUTXO>,
@@ -518,7 +593,10 @@ impl From<ContractDataV3> for ContractData {
518593
} = c;
519594

520595
Self {
521-
config,
596+
config: LazyOption::new(
597+
StorageKey::Config,
598+
Some(config.get().clone().unwrap().into()),
599+
),
522600
accounts,
523601
utxos,
524602
unavailable_utxos,
@@ -529,7 +607,7 @@ impl From<ContractDataV3> for ContractData {
529607
extra_msg_relayer_white_list,
530608
post_action_receiver_id_white_list,
531609
post_action_msg_templates,
532-
unlimited_txs_white_list: IterableSet::new(StorageKey::UnlimitedTxsWhiteList),
610+
multi_txs_white_list: IterableSet::new(StorageKey::MultiTxsWhiteList),
533611
lost_found,
534612
acc_collected_protocol_fee,
535613
cur_available_protocol_fee,

contracts/satoshi-bridge/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ enum StorageKey {
9292
LostFound,
9393
PostActionMsgTemplates,
9494
ExtraMsgRelayerWhiteList,
95-
UnlimitedTxsWhiteList,
95+
MultiTxsWhiteList,
9696
}
9797

9898
#[derive(AccessControlRole, Deserialize, Serialize, Copy, Clone)]
@@ -120,7 +120,7 @@ pub struct ContractData {
120120
pub extra_msg_relayer_white_list: IterableSet<AccountId>,
121121
pub post_action_receiver_id_white_list: IterableSet<AccountId>,
122122
pub post_action_msg_templates: IterableMap<AccountId, HashSet<String>>,
123-
pub unlimited_txs_white_list: IterableSet<AccountId>,
123+
pub multi_txs_white_list: IterableSet<AccountId>,
124124
pub lost_found: IterableMap<AccountId, u128>,
125125
pub acc_collected_protocol_fee: u128,
126126
pub cur_available_protocol_fee: u128,
@@ -188,7 +188,7 @@ impl Contract {
188188
StorageKey::PostActionReceiverIdWhiteListWhiteList,
189189
),
190190
post_action_msg_templates: IterableMap::new(StorageKey::PostActionMsgTemplates),
191-
unlimited_txs_white_list: IterableSet::new(StorageKey::UnlimitedTxsWhiteList),
191+
multi_txs_white_list: IterableSet::new(StorageKey::MultiTxsWhiteList),
192192
lost_found: IterableMap::new(StorageKey::LostFound),
193193
acc_collected_protocol_fee: 0,
194194
cur_available_protocol_fee: 0,

contracts/satoshi-bridge/src/unit/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ pub fn init_contract() -> Contract {
7979
chain_signatures_root_public_key: None,
8080
change_address: None,
8181
unhealthy_utxo_amount: 1000,
82+
max_pending_sign_txs: 1,
8283
#[cfg(feature = "zcash")]
8384
expiry_height_gap: 1000,
8485
})

contracts/satoshi-bridge/tests/setup/context.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ impl Context {
210210
"rbf_num_limit": 99,
211211
"max_btc_tx_pending_sec": 3600 * 24,
212212
"unhealthy_utxo_amount": 1000,
213+
"max_pending_sign_txs": 1,
213214
"expiry_height_gap": 5000,
214215
}
215216
}))

0 commit comments

Comments
 (0)