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

feat(spectests): fix timeout and run in CI #456

Merged
merged 1 commit into from
Oct 9, 2023
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
40 changes: 40 additions & 0 deletions .github/workflows/compliance.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
on:
push:
branches:
- main
pull_request:

name: compliance
jobs:
compliance:
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v3
with:
submodules: recursive
- name: Cache Docker layers
uses: actions/cache@v2
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
- uses: actions/setup-node@v3
with:
node-version: 18
cache: 'yarn'
cache-dependency-path: test/spec-tests/bundler-spec-tests/@account-abstraction/yarn.lock
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
- name: Setup PDM
uses: pdm-project/setup-pdm@v3
with:
cache: true
cache-dependency-path: '**/pdm.lock'
- name: Run spec tests
run: ./test/spec-tests/ci/run-spec-tests.sh
- name: Move cache
run: |
rm -rf /tmp/.buildx-cache
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
0xfourzerofour marked this conversation as resolved.
Show resolved Hide resolved
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/builder/proto/builder/builder.proto
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ message DebugSendBundleNowResponse {
}
message DebugSendBundleNowSuccess {
bytes transaction_hash = 1;
uint64 block_number = 2;
}

message DebugSetBundlingModeRequest {
Expand Down
70 changes: 32 additions & 38 deletions crates/builder/src/bundle_sender.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,9 @@
// You should have received a copy of the GNU General Public License along with Rundler.
// If not, see https://www.gnu.org/licenses/.

use std::{
sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
time::Duration,
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
};

use anyhow::{bail, Context};
Expand All @@ -31,7 +28,6 @@ use rundler_utils::emit::WithEntryPoint;
use tokio::{
join,
sync::{broadcast, mpsc, oneshot},
time,
};
use tracing::{error, info, trace, warn};

Expand Down Expand Up @@ -65,7 +61,6 @@ where
send_bundle_receiver: mpsc::Receiver<SendBundleRequest>,
chain_id: u64,
beneficiary: Address,
eth_poll_interval: Duration,
proposer: P,
entry_point: E,
transaction_tracker: T,
Expand Down Expand Up @@ -141,44 +136,45 @@ where

loop {
let mut send_bundle_response: Option<oneshot::Sender<SendBundleResult>> = None;
let mut last_block = None;

if self.manual_bundling_mode.load(Ordering::Relaxed) {
tokio::select! {
Some(r) = self.send_bundle_receiver.recv() => {
send_bundle_response = Some(r.responder);
}
_ = time::sleep(self.eth_poll_interval) => {
continue;
}
if let Some(r) = self.send_bundle_receiver.recv().await {
send_bundle_response = Some(r.responder);
} else {
error!("Bundle stream closed in manual mode");
bail!("Bundle stream closed in manual mode");
}
}
} else {
// Wait for new block. Block number doesn't matter as the pool will only notify of new blocks
// after the pool has updated its state. The bundle will be formed using the latest pool state
// and can land in the next block
last_block = rx.recv().await;

// Wait for new block. Block number doesn't matter as the pool will only notify of new blocks
// after the pool has updated its state. The bundle will be formed using the latest pool state
// and can land in the next block
let mut last_block = match rx.recv().await {
Some(b) => b,
None => {
if last_block.is_none() {
error!("Block stream closed");
bail!("Block stream closed");
}
};
// Consume any other blocks that may have been buffered up
loop {
match rx.try_recv() {
Ok(b) => {
last_block = b;
}
Err(mpsc::error::TryRecvError::Empty) => {
break;
}
Err(mpsc::error::TryRecvError::Disconnected) => {
error!("Block stream closed");
bail!("Block stream closed");
// Consume any other blocks that may have been buffered up
loop {
match rx.try_recv() {
Ok(b) => {
last_block = Some(b);
}
Err(mpsc::error::TryRecvError::Empty) => {
break;
}
Err(mpsc::error::TryRecvError::Disconnected) => {
error!("Block stream closed");
bail!("Block stream closed");
}
}
}
}

// Wait for new block. Block number doesn't matter as the pool will only notify of new blocks
// after the pool has updated its state. The bundle will be formed using the latest pool state
// and can land in the next block
self.check_for_and_log_transaction_update().await;
let result = self.send_bundle_with_increasing_gas_fees().await;
match &result {
Expand All @@ -192,7 +188,7 @@ where
} else {
info!("Bundle with hash {tx_hash:?} landed in block {block_number} after increasing gas fees {attempt_number} time(s)");
}
SendBundleResult::NoOperationsInitially => trace!("No ops to send at block {}", last_block.block_number),
SendBundleResult::NoOperationsInitially => trace!("No ops to send at block {}", last_block.unwrap_or_default().block_number),
SendBundleResult::NoOperationsAfterFeeIncreases {
initial_op_count,
attempt_number,
Expand Down Expand Up @@ -227,7 +223,6 @@ where
send_bundle_receiver: mpsc::Receiver<SendBundleRequest>,
chain_id: u64,
beneficiary: Address,
eth_poll_interval: Duration,
proposer: P,
entry_point: E,
transaction_tracker: T,
Expand All @@ -241,7 +236,6 @@ where
send_bundle_receiver,
chain_id,
beneficiary,
eth_poll_interval,
proposer,
entry_point,
transaction_tracker,
Expand Down
10 changes: 5 additions & 5 deletions crates/builder/src/server/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,11 @@ impl BuilderServer for LocalBuilderHandle {
}
}

async fn debug_send_bundle_now(&self) -> BuilderResult<H256> {
async fn debug_send_bundle_now(&self) -> BuilderResult<(H256, u64)> {
let req = ServerRequestKind::DebugSendBundleNow;
let resp = self.send(req).await?;
match resp {
ServerResponse::DebugSendBundleNow { hash } => Ok(hash),
ServerResponse::DebugSendBundleNow { hash, block_number } => Ok((hash, block_number)),
_ => Err(BuilderServerError::UnexpectedResponse),
}
}
Expand Down Expand Up @@ -197,8 +197,8 @@ impl LocalBuilderServerRunner {
};

match result {
SendBundleResult::Success { tx_hash, .. } => {
Ok(ServerResponse::DebugSendBundleNow { hash: tx_hash })
SendBundleResult::Success { tx_hash, block_number, .. } => {
Ok(ServerResponse::DebugSendBundleNow { hash: tx_hash, block_number })
},
SendBundleResult::NoOperationsInitially => {
Err(anyhow::anyhow!("no ops to send").into())
Expand Down Expand Up @@ -242,6 +242,6 @@ struct ServerRequest {
#[derive(Clone, Debug)]
enum ServerResponse {
GetSupportedEntryPoints { entry_points: Vec<Address> },
DebugSendBundleNow { hash: H256 },
DebugSendBundleNow { hash: H256, block_number: u64 },
DebugSetBundlingMode,
}
2 changes: 1 addition & 1 deletion crates/builder/src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pub trait BuilderServer: Send + Sync + 'static {
/// Trigger the builder to send a bundle now, used for debugging.
///
/// Bundling mode must be set to `Manual`, or this will error
async fn debug_send_bundle_now(&self) -> BuilderResult<H256>;
async fn debug_send_bundle_now(&self) -> BuilderResult<(H256, u64)>;

/// Set the bundling mode
async fn debug_set_bundling_mode(&self, mode: BundlingMode) -> BuilderResult<()>;
Expand Down
4 changes: 2 additions & 2 deletions crates/builder/src/server/remote/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ impl BuilderServer for RemoteBuilderClient {
.collect::<Result<_, ConversionError>>()?)
}

async fn debug_send_bundle_now(&self) -> BuilderResult<H256> {
async fn debug_send_bundle_now(&self) -> BuilderResult<(H256, u64)> {
let res = self
.grpc_client
.clone()
Expand All @@ -80,7 +80,7 @@ impl BuilderServer for RemoteBuilderClient {

match res {
Some(debug_send_bundle_now_response::Result::Success(s)) => {
Ok(H256::from_slice(&s.transaction_hash))
Ok((H256::from_slice(&s.transaction_hash), s.block_number))
}
Some(debug_send_bundle_now_response::Result::Failure(f)) => Err(f.try_into()?),
None => Err(BuilderServerError::Other(anyhow::anyhow!(
Expand Down
3 changes: 2 additions & 1 deletion crates/builder/src/server/remote/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,11 @@ impl GrpcBuilder for GrpcBuilderServerImpl {
_request: Request<DebugSendBundleNowRequest>,
) -> tonic::Result<Response<DebugSendBundleNowResponse>> {
let resp = match self.local_builder.debug_send_bundle_now().await {
Ok(hash) => DebugSendBundleNowResponse {
Ok((hash, block_number)) => DebugSendBundleNowResponse {
result: Some(debug_send_bundle_now_response::Result::Success(
DebugSendBundleNowSuccess {
transaction_hash: hash.as_bytes().to_vec(),
block_number,
},
)),
},
Expand Down
1 change: 0 additions & 1 deletion crates/builder/src/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,6 @@ where
send_bundle_rx,
self.args.chain_id,
beneficiary,
self.args.eth_poll_interval,
proposer,
entry_point,
transaction_tracker,
Expand Down
2 changes: 1 addition & 1 deletion crates/builder/src/transaction_tracker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ where
let nonce = provider
.get_transaction_count(sender.address())
.await
.context("tracker should load initial nonce on construction")?;
.unwrap_or(U256::zero());
0xfourzerofour marked this conversation as resolved.
Show resolved Hide resolved
Ok(Self {
provider,
sender,
Expand Down
9 changes: 9 additions & 0 deletions crates/pool/src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ pub struct NewHead {
pub block_number: u64,
}

impl Default for NewHead {
fn default() -> NewHead {
NewHead {
block_hash: H256::zero(),
block_number: 0,
}
}
}

/// Pool server trait
#[cfg_attr(feature = "test-utils", automock)]
#[async_trait]
Expand Down
1 change: 1 addition & 0 deletions crates/rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ tracing.workspace = true
serde.workspace = true
strum.workspace = true
url.workspace = true
futures-util.workspace = true
31 changes: 29 additions & 2 deletions crates/rpc/src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use async_trait::async_trait;
use ethers::types::{Address, H256};
use futures_util::StreamExt;
use jsonrpsee::{core::RpcResult, proc_macros::rpc, types::error::INTERNAL_ERROR_CODE};
use rundler_builder::{BuilderServer, BundlingMode};
use rundler_pool::PoolServer;
Expand Down Expand Up @@ -95,10 +96,36 @@ where
}

async fn bundler_send_bundle_now(&self) -> RpcResult<H256> {
self.builder
let mut new_heads = self
.pool
.subscribe_new_heads()
.await
.map_err(|e| rpc_err(INTERNAL_ERROR_CODE, e.to_string()))?;

let (tx, block_number) = self
.builder
.debug_send_bundle_now()
.await
.map_err(|e| rpc_err(INTERNAL_ERROR_CODE, e.to_string()))
.map_err(|e| rpc_err(INTERNAL_ERROR_CODE, e.to_string()))?;

// After the bundle is sent, we need to make sure that the mempool
// has processes the same block that the transaction was mined on.
// This removes the potential for an incorrect response from `debug_bundler_dumpMempool`
// method.
loop {
0xfourzerofour marked this conversation as resolved.
Show resolved Hide resolved
match new_heads.next().await {
Some(b) => {
if b.block_number.eq(&block_number) {
break;
}
}
None => {
return Err(rpc_err(INTERNAL_ERROR_CODE, "Next block not available"));
}
}
}

Ok(tx)
}

async fn bundler_set_bundling_mode(&self, mode: BundlingMode) -> RpcResult<String> {
Expand Down
2 changes: 1 addition & 1 deletion test/spec-tests/bundler-spec-tests
8 changes: 5 additions & 3 deletions test/spec-tests/ci/run-spec-tests.sh
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#!/bin/bash
set -x
set -e
cd "$(dirname "$0")"

(cd ../bundler-spec-tests && pdm install && pdm run update-deps)

docker build ../../.. -t alchemy-platform/rundler:latest

(cd ../bundler-spec-tests && pdm run test --launcher-script=../launchers/rundler-launcher/rundler-launcher.sh $@)
docker buildx create --use
docker buildx build --load --cache-from type=local,src=/tmp/.buildx-cache --cache-to type=local,mode=max,dest=/tmp/.buildx-cache-new -t alchemy-platform/rundler:latest ../../..

(cd ../bundler-spec-tests && pdm run test --url http://127.0.0.1:3000 --launcher-script=../launchers/rundler-launcher/rundler-launcher.sh $@)

../launchers/rundler-launcher/rundler-launcher.sh stop
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@ version: "3.8"
services:
rundler:
image: alchemy-platform/rundler:$TAG
depends_on:
- geth
ports:
- "3000:3000"
- "8080:8080"
command: bash -c "sleep 10; /usr/local/bin/rundler node"
command: bash -c "/usr/local/bin/rundler node"
environment:
- RUST_LOG=debug
- ENTRY_POINTS=0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789
Expand All @@ -17,7 +15,7 @@ services:
- MIN_UNSTAKE_DELAY=2
- BUILDER_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
healthcheck:
test: curl --fail http://localhost:3000/health || exit 1
test: curl --fail http://rundler:3000/health || exit 1
interval: 1s
timeout: 1s
retries: 60
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ case $1 in
;;

start)
docker-compose up -d --wait
cast send --from $(cast rpc eth_accounts | tail -n 1 | tr -d '[]"') --value 1ether 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 > /dev/null
docker-compose up -d
./waitForServices.sh
cast send --from $(cast rpc eth_accounts | tail -n 1 | tr -d '[]"') --unlocked --value 1ether 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 > /dev/null
cd ../../bundler-spec-tests/@account-abstraction && yarn deploy --network localhost
;;
stop)
Expand Down
Loading
Loading