Skip to content

Commit

Permalink
Merge pull request #246 from multiversx/update-pending-transactions-t…
Browse files Browse the repository at this point in the history
…o-map-mapper

update pending transactions to map mapper
  • Loading branch information
iulianpascalau authored Oct 30, 2024
2 parents 2bf5ff9 + a1335fa commit ad2178e
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 120 deletions.
55 changes: 15 additions & 40 deletions bridge-proxy/src/bridge-proxy.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#![no_std]
use multiversx_sc::imports::*;
use multiversx_sc_modules::ongoing_operation::*;

pub mod bridge_proxy_contract_proxy;
pub mod bridged_tokens_wrapper_proxy;
Expand All @@ -12,18 +11,15 @@ const MIN_GAS_LIMIT_FOR_SC_CALL: u64 = 10_000_000;
const MAX_GAS_LIMIT_FOR_SC_CALL: u64 = 249999999;
const DEFAULT_GAS_LIMIT_FOR_REFUND_CALLBACK: u64 = 20_000_000; // 20 million
const DELAY_BEFORE_OWNER_CAN_CANCEL_TRANSACTION: u64 = 300;
const MIN_GAS_TO_SAVE_PROGRESS: u64 = 1_000_000;

#[multiversx_sc::contract]
pub trait BridgeProxyContract:
config::ConfigModule
+ multiversx_sc_modules::pause::PauseModule
+ multiversx_sc_modules::ongoing_operation::OngoingOperationModule
{
#[init]
fn init(&self, opt_multi_transfer_address: OptionalValue<ManagedAddress>) {
self.set_multi_transfer_contract_address(opt_multi_transfer_address);
self.lowest_tx_id().set(1);
self.set_paused(true);
}

Expand All @@ -42,9 +38,10 @@ pub trait BridgeProxyContract:
caller == self.multi_transfer_address().get(),
"Only MultiTransfer can do deposits"
);
let tx_id = self.pending_transactions().push(&eth_tx);
self.payments(tx_id).set(&payment);
self.batch_id(tx_id).set(batch_id);
let next_tx_id = self.get_next_tx_id();
self.pending_transactions().insert(next_tx_id, eth_tx);
self.payments(next_tx_id).set(&payment);
self.batch_id(next_tx_id).set(batch_id);
}

#[endpoint(execute)]
Expand Down Expand Up @@ -193,53 +190,31 @@ pub trait BridgeProxyContract:
}

fn cleanup_transaction(&self, tx_id: usize) {
self.pending_transactions().clear_entry_unchecked(tx_id);
self.update_lowest_tx_id();
self.pending_transactions().remove(&tx_id);
self.ongoing_execution(tx_id).clear();
}

#[endpoint(updateLowestTxId)]
fn update_lowest_tx_id(&self) {
let mut new_lowest = self.lowest_tx_id().get();
let len = self.pending_transactions().len();

self.run_while_it_has_gas(MIN_GAS_TO_SAVE_PROGRESS, || {
if !self.empty_element(new_lowest, len) {
return STOP_OP;
}

new_lowest += 1;

CONTINUE_OP
});

self.lowest_tx_id().set(new_lowest);
}

fn empty_element(&self, current_index: usize, len: usize) -> bool {
current_index < len && self.pending_transactions().item_is_empty(current_index)
fn get_next_tx_id(&self) -> usize {
let mut next_tx_id = self.highest_tx_id().get();
next_tx_id += 1;
self.highest_tx_id().set(next_tx_id);
next_tx_id
}

#[view(getPendingTransactionById)]
fn get_pending_transaction_by_id(&self, tx_id: usize) -> EthTransaction<Self::Api> {
self.pending_transactions()
.get_or_else(tx_id, || panic!("Invalid tx id"))
let tx = self.pending_transactions().get(&tx_id);
require!(tx.is_some(), "Invalid tx id");
tx.unwrap()
}

#[view(getPendingTransactions)]
fn get_pending_transactions(
&self,
) -> MultiValueEncoded<MultiValue2<usize, EthTransaction<Self::Api>>> {
let lowest_tx_id = self.lowest_tx_id().get();
let len = self.pending_transactions().len();

let mut transactions = MultiValueEncoded::new();
for i in lowest_tx_id..=len {
if self.pending_transactions().item_is_empty(i) {
continue;
}
let tx = self.pending_transactions().get_unchecked(i);
transactions.push(MultiValue2((i, tx)));
for (tx_id, tx) in self.pending_transactions().iter() {
transactions.push(MultiValue2((tx_id, tx)));
}
transactions
}
Expand Down
13 changes: 2 additions & 11 deletions bridge-proxy/src/bridge_proxy_contract_proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,6 @@ where
.original_result()
}

pub fn update_lowest_tx_id(
self,
) -> TxTypedCall<Env, From, To, NotPayable, Gas, ()> {
self.wrapped_tx
.payment(NotPayable)
.raw_call("updateLowestTxId")
.original_result()
}

pub fn get_pending_transaction_by_id<
Arg0: ProxyArg<usize>,
>(
Expand Down Expand Up @@ -210,12 +201,12 @@ where
.original_result()
}

pub fn lowest_tx_id(
pub fn highest_tx_id(
self,
) -> TxTypedCall<Env, From, To, NotPayable, Gas, usize> {
self.wrapped_tx
.payment(NotPayable)
.raw_call("lowestTxId")
.raw_call("highestTxId")
.original_result()
}

Expand Down
8 changes: 4 additions & 4 deletions bridge-proxy/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,17 @@ pub trait ConfigModule {
fn esdt_safe_contract_address(&self) -> SingleValueMapper<ManagedAddress>;

#[storage_mapper("pending_transactions")]
fn pending_transactions(&self) -> VecMapper<EthTransaction<Self::Api>>;
fn pending_transactions(&self) -> MapMapper<usize, EthTransaction<Self::Api>>;

#[storage_mapper("payments")]
fn payments(&self, tx_id: usize) -> SingleValueMapper<EsdtTokenPayment<Self::Api>>;

#[storage_mapper("batch_id")]
fn batch_id(&self, tx_id: usize) -> SingleValueMapper<u64>;

#[view(lowestTxId)]
#[storage_mapper("lowest_tx_id")]
fn lowest_tx_id(&self) -> SingleValueMapper<usize>;
#[view(highestTxId)]
#[storage_mapper("highest_tx_id")]
fn highest_tx_id(&self) -> SingleValueMapper<usize>;

#[storage_mapper("ongoingExecution")]
fn ongoing_execution(&self, tx_id: usize) -> SingleValueMapper<u64>;
Expand Down
56 changes: 17 additions & 39 deletions bridge-proxy/tests/bridge_proxy_blackbox_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ fn multiple_deposit_test() {
}

#[test]
fn test_lowest_tx_id() {
fn test_highest_tx_id() {
let mut test = BridgeProxyTestState::new();

test.bridge_proxy_deploy();
Expand All @@ -441,9 +441,9 @@ fn test_lowest_tx_id() {
};
let call_data = ManagedSerializer::new().top_encode_to_managed_buffer(&call_data);

// Generate 100 transactions
// Generate 1600 transactions
let mut transactions = Vec::new();
for i in 1..=100 {
for i in 1..=1600 {
let eth_tx = EthTransaction {
from: EthAddress {
raw_addr: ManagedByteArray::new_from_bytes(b"01020304050607080910"),
Expand All @@ -456,8 +456,16 @@ fn test_lowest_tx_id() {
};
transactions.push(eth_tx);
}
test.world
.query()
.to(BRIDGE_PROXY_ADDRESS)
.typed(bridge_proxy_contract_proxy::BridgeProxyContractProxy)
.highest_tx_id()
.returns(ExpectValue(0usize))
.run();

// Deposit all transactions
let mut expected_tx_id = 1usize;
for tx in &transactions {
test.world
.tx()
Expand All @@ -471,40 +479,19 @@ fn test_lowest_tx_id() {
&BigUint::from(5u64),
)
.run();
}

// Check the lowest_tx_id
test.world
.query()
.to(BRIDGE_PROXY_ADDRESS)
.typed(bridge_proxy_contract_proxy::BridgeProxyContractProxy)
.lowest_tx_id()
.returns(ExpectValue(1usize))
.run();

// Execute the first 50 transactions
for i in 1..=50usize {
test.world
.tx()
.from(OWNER_ADDRESS)
.query()
.to(BRIDGE_PROXY_ADDRESS)
.gas(200_000_000)
.typed(bridge_proxy_contract_proxy::BridgeProxyContractProxy)
.execute(i)
.highest_tx_id()
.returns(ExpectValue(expected_tx_id))
.run();
expected_tx_id += 1;
}

// Check the lowest_tx_id again
test.world
.query()
.to(BRIDGE_PROXY_ADDRESS)
.typed(bridge_proxy_contract_proxy::BridgeProxyContractProxy)
.lowest_tx_id()
.returns(ExpectValue(51usize))
.run();

// Execute transactions 75 to 100
for i in 75..=100usize {
// Execute all transactions
for i in (1..=1600usize).rev() {
test.world
.tx()
.from(OWNER_ADDRESS)
Expand All @@ -514,13 +501,4 @@ fn test_lowest_tx_id() {
.execute(i)
.run();
}

// Check the lowest_tx_id one last time
test.world
.query()
.to(BRIDGE_PROXY_ADDRESS)
.typed(bridge_proxy_contract_proxy::BridgeProxyContractProxy)
.lowest_tx_id()
.returns(ExpectValue(51usize))
.run();
}
7 changes: 3 additions & 4 deletions bridge-proxy/wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@

// Init: 1
// Upgrade: 1
// Endpoints: 15
// Endpoints: 14
// Async Callback (empty): 1
// Promise callbacks: 1
// Total number of exported functions: 19
// Total number of exported functions: 18

#![no_std]

Expand All @@ -23,7 +23,6 @@ multiversx_sc_wasm_adapter::endpoints! {
upgrade => upgrade
deposit => deposit
execute => execute
updateLowestTxId => update_lowest_tx_id
getPendingTransactionById => get_pending_transaction_by_id
getPendingTransactions => get_pending_transactions
setMultiTransferAddress => set_multi_transfer_contract_address
Expand All @@ -32,7 +31,7 @@ multiversx_sc_wasm_adapter::endpoints! {
getMultiTransferAddress => multi_transfer_address
getBridgedTokensWrapperAddress => bridged_tokens_wrapper_address
getEsdtSafeContractAddress => esdt_safe_contract_address
lowestTxId => lowest_tx_id
highestTxId => highest_tx_id
pause => pause_endpoint
unpause => unpause_endpoint
isPaused => paused_status
Expand Down
13 changes: 2 additions & 11 deletions multi-transfer-esdt/src/bridge_proxy_contract_proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,6 @@ where
.original_result()
}

pub fn update_lowest_tx_id(
self,
) -> TxTypedCall<Env, From, To, NotPayable, Gas, ()> {
self.wrapped_tx
.payment(NotPayable)
.raw_call("updateLowestTxId")
.original_result()
}

pub fn get_pending_transaction_by_id<
Arg0: ProxyArg<usize>,
>(
Expand Down Expand Up @@ -210,12 +201,12 @@ where
.original_result()
}

pub fn lowest_tx_id(
pub fn highest_tx_id(
self,
) -> TxTypedCall<Env, From, To, NotPayable, Gas, usize> {
self.wrapped_tx
.payment(NotPayable)
.raw_call("lowestTxId")
.raw_call("highestTxId")
.original_result()
}

Expand Down
13 changes: 2 additions & 11 deletions multisig/src/bridge_proxy_contract_proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,6 @@ where
.original_result()
}

pub fn update_lowest_tx_id(
self,
) -> TxTypedCall<Env, From, To, NotPayable, Gas, ()> {
self.wrapped_tx
.payment(NotPayable)
.raw_call("updateLowestTxId")
.original_result()
}

pub fn get_pending_transaction_by_id<
Arg0: ProxyArg<usize>,
>(
Expand Down Expand Up @@ -210,12 +201,12 @@ where
.original_result()
}

pub fn lowest_tx_id(
pub fn highest_tx_id(
self,
) -> TxTypedCall<Env, From, To, NotPayable, Gas, usize> {
self.wrapped_tx
.payment(NotPayable)
.raw_call("lowestTxId")
.raw_call("highestTxId")
.original_result()
}

Expand Down

0 comments on commit ad2178e

Please sign in to comment.