Skip to content

Commit 8298745

Browse files
authored
Debugging of pythn bindings. Last mile. (astraly-labs#7)
* added get_balance method to env added missing python bindings added sync get_block_events method (turned out subscriptions are pointless) * Added get_all_events to cheating provider and to python bindings Added some debugging info * more methods needed: - get_deployed_address - get_token * fix ekubo core compiled contract data * small fix * Added some bullet point not to forget.
1 parent 035fff2 commit 8298745

19 files changed

Lines changed: 794 additions & 277 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ The Starkbiter workspace has five crates:
3030

3131
## WIP
3232

33-
- [ ] non-blocking event polling
3433
- [x] bin docs
3534
- [x] core docs
3635
- [x] main readme
@@ -39,17 +38,24 @@ The Starkbiter workspace has five crates:
3938
- [ ] usage
4039
- [x] index
4140
- [ ] benchmarks
42-
- [ ] python bindings
41+
- [x] python bindings
4342
- [x] more test cases
44-
- [ ] coverage report
4543
- [x] support for replaying mainnet transactions mixing them with simulated ones.
4644
- [x] github workflows revival
47-
- [ ] contribute to cainome and remove fork dep
48-
- [ ] contribute to starknet-rs and remove fork dep + Fix generic Runtime error with more specific errors from within Provider
49-
- [ ] contribute to starknet-devnet and remove fork dep
5045
- [x] test that toml config parameters for forking work
5146
- [x] contract execution logging and traces from Devnet
52-
- [ ] test for simultaneous connection usage by different contracts.
47+
- [x] test for simultaneous connection usage by different contracts.
48+
- [ ] contribute to cainome and remove fork dep
49+
- [ ] contribute to starknet-rs and remove fork dep + Fix generic Runtime error with more specific errors from within Provider
50+
- [ ] Contribute to starknet-devnet and remove fork dep
51+
- [ ] Coverage report
52+
- [ ] Python binding add validation (last minute changes were dirty)
53+
- [ ] Type conversions. need to replace Into with From
54+
- [ ] Type conversions. remove Clone where possible
55+
- [ ] Environment. Move handler processing logic in separate files.
56+
- [ ] Make explicit naming for methods that only work with local data and ones that work against remote state
57+
- [ ] Add API to preload state and save it to file. (like EKUBO core contract storage)
58+
- [ ] Test approach to set local nonce before adding transaction to bypass validation (less remote calls)
5359

5460

5561
## Book

bindings/src/lib.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,9 @@ pub static ERC20_CONTRACT_SIERRA: &str =
1818

1919
pub static ARGENT_V040_SIERRA: &str = include_str!("../contracts/ArgentAccount.0.4.0.class.json");
2020

21-
pub static SWAPPER_CONTRACT_SIERRA: &str =
22-
include_str!("../contracts/contracts_Swapper.contract_class.json");
21+
pub static EKUBO_CORE_CONTRACT_SIERRA: &str = include_str!("../contracts/EkuboCore.class.json");
2322

24-
pub static EKUBO_CORE_CONTRACT_SIERRA: &str =
23+
pub static SWAPPER_CONTRACT_SIERRA: &str =
2524
include_str!("../contracts/contracts_Swapper.contract_class.json");
2625

2726
pub static EKUBO_ROUTER_LITE_CONTRACT_SIERRA: &str =

core/src/environment/instruction.rs

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ use crate::tokens::TokenId;
2424
pub struct EventFilter {
2525
/// Matched events emitted by this address
2626
pub from_address: Felt,
27-
/// Matches events with those keys: [selector, key1, key2]
27+
/// Matches events against keys list: vec![vec![selector, key1, key2]]
2828
/// selector is a keccak hash from event name.
29-
pub keys: Vec<Felt>,
29+
pub keys: Vec<Vec<Felt>>,
3030
}
3131

3232
/// Instructions that can be sent to the [`Environment`] via the [`Socket`].
@@ -398,6 +398,13 @@ pub enum CheatInstruction {
398398
/// The token symbol or identifier.
399399
token: TokenId, // need to create classifier
400400
},
401+
/// Fetches token balance for an account.
402+
GetBalance {
403+
/// The address to check.
404+
address: Felt,
405+
/// The token symbol or identifier.
406+
token: TokenId, // need to create classifier
407+
},
401408
/// Starts impersonation. Skips transaction validation if sent on behalf of
402409
/// an account with impersonated address.
403410
Impersonate {
@@ -447,6 +454,21 @@ pub enum CheatInstruction {
447454
/// Set to true to recalculate the nonce for the transactions
448455
override_nonce: bool,
449456
},
457+
458+
/// Fetches all events from block in one go. Only scans local blocks
459+
GetAllEvents {
460+
/// Block id of a the block to fetch events from. If `None`, fetches all
461+
/// events since fork start.
462+
from_block: Option<core_types::BlockId>,
463+
/// Block id to fetch events till. If `None`, fetches all events from
464+
/// from_block
465+
to_block: Option<core_types::BlockId>,
466+
/// The address that emitted events to filter events by. If `None`,
467+
/// fetches all events.
468+
address: Option<Felt>,
469+
/// The keys to filter events by. If `None`, fetches all events.
470+
keys: Option<Vec<Vec<Felt>>>,
471+
},
450472
}
451473

452474
/// Return values of applying cheatcodes.
@@ -456,12 +478,14 @@ pub enum CheatcodesOutcome {
456478
DeclareContract(Felt),
457479
/// Returns the contract address of the created account.
458480
CreateAccount(Felt),
459-
/// Indicates a block was created.
460-
CreateBlock,
481+
/// Indicates a block was created. Returns latest block hash.
482+
CreateBlock(Felt),
461483
/// Returns the tx_hash of L1 message transaction.
462484
L1Message(Felt),
463485
/// Indicates a balance was added.
464486
TopUpBalance,
487+
/// Returns amount of token owned.
488+
GetBalance(BigUint),
465489
/// Indicates the address was impersonated.
466490
Impersonate,
467491
/// Indicates the impersonation was stopped.
@@ -478,4 +502,7 @@ pub enum CheatcodesOutcome {
478502
/// Returns numbers of transactions from the origin block that were (added,
479503
/// ignored, failed)
480504
ReplayBlockWithTxs(usize, usize, usize),
505+
506+
/// Returns all events matching the filter.
507+
GetAllEvents(Vec<core_types::EmittedEvent>),
481508
}

core/src/environment/mod.rs

Lines changed: 124 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ use starknet_devnet_types::{
6161
traits::HashProducer,
6262
};
6363
use tokio::sync::broadcast::channel;
64+
use tracing::debug;
6465

6566
use super::*;
6667
use crate::tokens::get_token_data;
@@ -1412,7 +1413,17 @@ async fn process_instructions(
14121413

14131414
event_broadcaster.send(converted).unwrap_or_default();
14141415

1415-
let outcome = Ok(Outcome::Cheat(instruction::CheatcodesOutcome::CreateBlock));
1416+
let latest_block = starknet.get_latest_block().unwrap();
1417+
1418+
trace!(
1419+
"Environment. Created latest block: {:?}, {:?}",
1420+
latest_block.block_hash(),
1421+
latest_block.block_number(),
1422+
);
1423+
1424+
let outcome = Ok(Outcome::Cheat(instruction::CheatcodesOutcome::CreateBlock(
1425+
latest_block.block_hash(),
1426+
)));
14161427
if let Err(e) = sender.send(outcome) {
14171428
error!("Failed to send CreateBlock outcome: {:?}", e);
14181429
stop = true;
@@ -1771,29 +1782,27 @@ async fn process_instructions(
17711782
{
17721783
trace!(
17731784
"Skipping transaction with reverted execution result: {:?}",
1774-
tx
1785+
tx.receipt.transaction_hash()
17751786
);
17761787
continue;
17771788
};
17781789

17791790
if let Some(filters) = filters {
17801791
let has_events = tx.receipt.events().iter().any(|e| {
17811792
filters.iter().any(|f| {
1782-
let res = e.from_address == f.from_address && e.keys == f.keys;
1783-
if res {
1784-
trace!(
1785-
"Hash: {:?}, Event: {:?}, Filter: {:?}",
1786-
tx.receipt.transaction_hash(),
1787-
e,
1788-
f
1789-
);
1793+
if e.from_address != f.from_address {
1794+
return false;
1795+
}
1796+
1797+
if !f.keys.iter().any(|keys| e.keys == *keys) {
1798+
return false;
17901799
}
1791-
res
1800+
1801+
true
17921802
})
17931803
});
17941804

17951805
if !has_events {
1796-
trace!("No events that match filter. Ignoring the transaction.");
17971806
ignored_tx += 1;
17981807
continue;
17991808
}
@@ -1905,7 +1914,6 @@ async fn process_instructions(
19051914
.map(|res| res.0)
19061915
}
19071916
_ => {
1908-
trace!("TX: {:?}", tx);
19091917
ignored_tx += 1;
19101918
Ok(core_types::Felt::ZERO)
19111919
}
@@ -1915,16 +1923,18 @@ async fn process_instructions(
19151923
error!("Failed to add transaction: {:?}", e);
19161924
failed_tx += 1;
19171925
} else {
1918-
info!(
1919-
"Transaction processed: {} of {}. Ignored: {}",
1920-
added_tx,
1921-
txs.len(),
1922-
ignored_tx
1923-
);
19241926
added_tx += 1;
19251927
}
19261928
}
19271929

1930+
debug!(
1931+
"Transaction processed: {} of {}. Ignored: {}. Failed: {}",
1932+
added_tx,
1933+
txs.len(),
1934+
ignored_tx,
1935+
failed_tx
1936+
);
1937+
19281938
let outcome = Ok(Outcome::Cheat(
19291939
instruction::CheatcodesOutcome::ReplayBlockWithTxs(
19301940
added_tx, ignored_tx, failed_tx,
@@ -1936,6 +1946,101 @@ async fn process_instructions(
19361946
stop = true;
19371947
}
19381948
}
1949+
instruction::CheatInstruction::GetBalance { address, token } => {
1950+
trace!(
1951+
"Environment. Received GetBalance instruction: address: {:?}, token: {:?}",
1952+
address,
1953+
token
1954+
);
1955+
1956+
let state = starknet.get_state();
1957+
1958+
let address = ContractAddress::new(*address);
1959+
if let Err(e) = address {
1960+
let outcome = Err(StarkbiterCoreError::InternalError(e.to_string()));
1961+
if let Err(e) = sender.send(outcome) {
1962+
error!("Failed to send GetBalance outcome: {:?}", e);
1963+
stop = true;
1964+
}
1965+
1966+
continue;
1967+
}
1968+
1969+
let token_data = get_token_data(&starknet_config.chain_id, token);
1970+
if let Err(e) = token_data {
1971+
let outcome = Err(StarkbiterCoreError::InternalError(e.to_string()));
1972+
if let Err(e) = sender.send(outcome) {
1973+
error!("Failed to send GetBalance outcome: {:?}", e);
1974+
stop = true;
1975+
}
1976+
1977+
continue;
1978+
}
1979+
1980+
let result = utils::read_tokens_in_erc20_contract(
1981+
state,
1982+
token_data.unwrap().l2_token_address,
1983+
address.unwrap().into(),
1984+
);
1985+
1986+
if let Err(e) = result {
1987+
if let Err(e) = sender.send(Err(*e)) {
1988+
error!("Failed to send GetBalance outcome: {:?}", e);
1989+
stop = true;
1990+
}
1991+
1992+
continue;
1993+
}
1994+
1995+
let outcome = Ok(Outcome::Cheat(instruction::CheatcodesOutcome::GetBalance(
1996+
result.unwrap(),
1997+
)));
1998+
if let Err(e) = sender.send(outcome) {
1999+
error!("Failed to send GetBalance outcome: {:?}", e);
2000+
stop = true;
2001+
}
2002+
}
2003+
instruction::CheatInstruction::GetAllEvents {
2004+
from_block,
2005+
to_block,
2006+
address,
2007+
keys,
2008+
} => {
2009+
trace!("Environment. Received GetAllEvents instruction");
2010+
2011+
let maybe_contract_address =
2012+
address.map(|addr| ContractAddress::new(addr).unwrap());
2013+
2014+
let events = starknet.get_unlimited_events(
2015+
*from_block,
2016+
*to_block,
2017+
maybe_contract_address,
2018+
keys.clone(),
2019+
);
2020+
2021+
if let Err(e) = events {
2022+
if let Err(e) = sender.send(Err(StarkbiterCoreError::DevnetError(e))) {
2023+
error!("Failed to send GetAllEvents outcome: {:?}", e);
2024+
stop = true;
2025+
}
2026+
continue;
2027+
}
2028+
2029+
let converted = events
2030+
.unwrap()
2031+
.iter()
2032+
.map(core_types::EmittedEvent::from)
2033+
.collect();
2034+
2035+
let outcome = Ok(Outcome::Cheat(
2036+
instruction::CheatcodesOutcome::GetAllEvents(converted),
2037+
));
2038+
2039+
if let Err(e) = sender.send(outcome) {
2040+
error!("Failed to send GetAllEvents outcome: {:?}", e);
2041+
stop = true;
2042+
}
2043+
}
19392044
},
19402045
Instruction::System(ref system_instruction) => match system_instruction {
19412046
instruction::SystemInstruction::Stop => {

0 commit comments

Comments
 (0)