diff --git a/esdt-safe/src/bls_signature.rs b/esdt-safe/src/bls_signature.rs deleted file mode 100644 index 2cea627b..00000000 --- a/esdt-safe/src/bls_signature.rs +++ /dev/null @@ -1,4 +0,0 @@ -multiversx_sc::imports!(); - -#[multiversx_sc::module] -pub trait BlsSignatureModule {} diff --git a/esdt-safe/src/lib.rs b/esdt-safe/src/lib.rs index d73c6375..bf9d2c9c 100644 --- a/esdt-safe/src/lib.rs +++ b/esdt-safe/src/lib.rs @@ -10,7 +10,6 @@ use tx_batch_module::FIRST_BATCH_ID; const DEFAULT_MAX_TX_BATCH_SIZE: usize = 10; const DEFAULT_MAX_TX_BATCH_BLOCK_DURATION: u64 = 100; // ~10 minutes -pub mod bls_signature; pub mod create_tx; pub mod events; pub mod refund; @@ -18,8 +17,7 @@ pub mod set_tx_status; #[multiversx_sc::contract] pub trait EsdtSafe: - bls_signature::BlsSignatureModule - + create_tx::CreateTxModule + create_tx::CreateTxModule + events::EventsModule + refund::RefundModule + set_tx_status::SetTxStatusModule diff --git a/multi-transfer-esdt/src/bls_signature.rs b/multi-transfer-esdt/src/bls_signature.rs new file mode 100644 index 00000000..b89e46f0 --- /dev/null +++ b/multi-transfer-esdt/src/bls_signature.rs @@ -0,0 +1,73 @@ +use transaction::Transaction; + +multiversx_sc::imports!(); + +pub const BLS_SIGNATURE_LEN: usize = 48; +pub type BlsSignature = ManagedByteArray; + +#[multiversx_sc::module] +pub trait BlsSignatureModule { + #[only_owner] + #[endpoint(setMinValidSigners)] + fn set_min_valid_signers(&self, new_value: u32) { + self.min_valid_signers().set(new_value); + } + + #[only_owner] + #[endpoint(addSigners)] + fn add_signers(&self, signers: MultiValueEncoded) { + for signer in signers { + let _ = self.all_signers().insert(signer); + } + } + + #[only_owner] + #[endpoint(removeSigners)] + fn remove_signers(&self, signers: MultiValueEncoded) { + for signer in signers { + let _ = self.all_signers().swap_remove(&signer); + } + } + + fn verify_bls_signature( + &self, + transactions: MultiValueEncoded>, + signature: &BlsSignature, + ) -> ManagedVec> { + let mut deserialized_transactions = ManagedVec::new(); + let mut serialized_signature_data = ManagedBuffer::new(); + for transaction in transactions { + let _ = transaction.dep_encode(&mut serialized_signature_data); + + deserialized_transactions.push(transaction); + } + + let all_signers = self.all_signers(); + + let mut total_valid_signatures = 0; + for signer in all_signers.iter() { + let is_valid = self.crypto().verify_bls( + signer.as_managed_buffer(), + &serialized_signature_data, + signature.as_managed_buffer(), + ); + if is_valid { + total_valid_signatures += 1; + } + } + + let min_valid_signers = self.min_valid_signers().get(); + require!( + total_valid_signatures >= min_valid_signers, + "Invalid signature" + ); + + deserialized_transactions + } + + #[storage_mapper("allSigners")] + fn all_signers(&self) -> UnorderedSetMapper; + + #[storage_mapper("minValidSigners")] + fn min_valid_signers(&self) -> SingleValueMapper; +} diff --git a/multi-transfer-esdt/src/lib.rs b/multi-transfer-esdt/src/lib.rs index 03ed4de1..52feffc6 100644 --- a/multi-transfer-esdt/src/lib.rs +++ b/multi-transfer-esdt/src/lib.rs @@ -7,20 +7,22 @@ use tx_batch_module::FIRST_BATCH_ID; const DEFAULT_MAX_TX_BATCH_SIZE: usize = 10; const DEFAULT_MAX_TX_BATCH_BLOCK_DURATION: u64 = u64::MAX; +pub mod bls_signature; pub mod events; pub mod refund; pub mod transfer_tokens; #[multiversx_sc::contract] pub trait MultiTransferEsdt: - events::EventsModule + bls_signature::BlsSignatureModule + + events::EventsModule + refund::RefundModule + transfer_tokens::TransferTokensModule + tx_batch_module::TxBatchModule + max_bridged_amount_module::MaxBridgedAmountModule { #[init] - fn init(&self) { + fn init(&self, min_valid_signers: u32, signers: MultiValueEncoded) { self.max_tx_batch_size().set(DEFAULT_MAX_TX_BATCH_SIZE); self.max_tx_batch_block_duration() .set(DEFAULT_MAX_TX_BATCH_BLOCK_DURATION); @@ -28,12 +30,11 @@ pub trait MultiTransferEsdt: // batch ID 0 is considered invalid self.first_batch_id().set(FIRST_BATCH_ID); self.last_batch_id().set(FIRST_BATCH_ID); + + self.set_min_valid_signers(min_valid_signers); + self.add_signers(signers); } #[endpoint] fn upgrade(&self) {} - - // private - - // events } diff --git a/multi-transfer-esdt/src/transfer_tokens.rs b/multi-transfer-esdt/src/transfer_tokens.rs index 9d42efca..27780243 100644 --- a/multi-transfer-esdt/src/transfer_tokens.rs +++ b/multi-transfer-esdt/src/transfer_tokens.rs @@ -4,13 +4,16 @@ use transaction::{ BatchId, GasLimit, PaymentsVec, StolenFromFrameworkEsdtTokenData, Transaction, TxNonce, }; +use crate::bls_signature::BlsSignature; + multiversx_sc::imports!(); const CALLBACK_GAS: GasLimit = 1_000_000; // Increase if not enough #[multiversx_sc::module] pub trait TransferTokensModule: - crate::events::EventsModule + crate::bls_signature::BlsSignatureModule + + crate::events::EventsModule + crate::refund::RefundModule + tx_batch_module::TxBatchModule + max_bridged_amount_module::MaxBridgedAmountModule @@ -20,16 +23,19 @@ pub trait TransferTokensModule: fn batch_transfer_esdt_token( &self, batch_id: BatchId, + signature: BlsSignature, transfers: MultiValueEncoded>, ) { let mut successful_tx_list = ManagedVec::new(); let mut all_tokens_to_send = ManagedVec::new(); let mut refund_tx_list = ManagedVec::new(); + let signed_transactions = self.verify_bls_signature(transfers, &signature); + let own_sc_address = self.blockchain().get_sc_address(); let sc_shard = self.blockchain().get_shard_of_address(&own_sc_address); - for sov_tx in transfers { + for sov_tx in &signed_transactions { let mut refund_tokens_for_user = ManagedVec::new(); let mut tokens_to_send = ManagedVec::new(); let mut sent_token_data = ManagedVec::new(); diff --git a/multi-transfer-esdt/wasm/src/lib.rs b/multi-transfer-esdt/wasm/src/lib.rs index f3844095..f6b3e1ce 100644 --- a/multi-transfer-esdt/wasm/src/lib.rs +++ b/multi-transfer-esdt/wasm/src/lib.rs @@ -5,10 +5,10 @@ //////////////////////////////////////////////////// // Init: 1 -// Endpoints: 13 +// Endpoints: 16 // Async Callback (empty): 1 // Promise callbacks: 1 -// Total number of exported functions: 16 +// Total number of exported functions: 19 #![no_std] @@ -24,6 +24,9 @@ multiversx_sc_wasm_adapter::endpoints! { ( init => init upgrade => upgrade + setMinValidSigners => set_min_valid_signers + addSigners => add_signers + removeSigners => remove_signers getAndClearFirstRefundBatch => get_and_clear_first_refund_batch batchTransferEsdtToken => batch_transfer_esdt_token setMaxTxBatchSize => set_max_tx_batch_size