Skip to content

Commit

Permalink
tx spammer and tx commit (#50)
Browse files Browse the repository at this point in the history
* tx spammer and tx commit

* description update
  • Loading branch information
mskrzypkows authored Jul 15, 2024
1 parent aaecabe commit 0e30434
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 30 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
/Node/target
.vscode
tools/tx_spammer/.env
tools/tx_spammer/venv
57 changes: 32 additions & 25 deletions Node/Cargo.lock

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

9 changes: 4 additions & 5 deletions Node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,11 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
alloy = { version = "0.1.2", features = [
"full",
"node-bindings",
] }
alloy = { version = "0.1.2", features = ["full", "node-bindings"] }
tokio = { version = "1.38", features = ["full"] }
tracing = "0.1.40"
tracing-subscriber = "0.3"
jsonrpsee = { version = "0.23", features = ["http-client", "server"] }
jsonrpsee = { version = "0.24", features = ["http-client", "server"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
lazy_static = "1.4"
Expand All @@ -22,3 +19,5 @@ k256 = "0.13"
elliptic-curve = "0.13"
reqwest = "0.12"
hex = "0.4"
tiny-keccak = "2.0"
secp256k1 = "0.29"
81 changes: 81 additions & 0 deletions Node/src/utils/commit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
use crate::taiko::l2_tx_lists::RPCReplyL2TxLists;
use anyhow::Error;
use secp256k1::{ecdsa::Signature, Message, Secp256k1, SecretKey};
use serde::{Deserialize, Serialize};
use tiny_keccak::{Hasher, Keccak};

#[derive(Serialize, Deserialize)]
pub struct L2TxListsCommit {
pub tx_list_bytes: Vec<u8>,
pub parent_meta_hash: [u8; 32],
pub block_height: u64,
}

impl From<RPCReplyL2TxLists> for L2TxListsCommit {
fn from(reply: RPCReplyL2TxLists) -> Self {
L2TxListsCommit {
tx_list_bytes: reply.tx_list_bytes[0].clone(), // TODO check for other indexes
parent_meta_hash: reply.parent_meta_hash,
block_height: 1, //TODO add to the replay
}
}
}

impl L2TxListsCommit {
pub fn hash(&self) -> Result<[u8; 32], Error> {
let serialized = serde_json::to_vec(&self)?;
let mut hasher = Keccak::v256();
hasher.update(&serialized);
let mut result = [0u8; 32];
hasher.finalize(&mut result);
Ok(result)
}

pub fn sign(&self, private_key: &str) -> Result<Signature, Error> {
let secp = Secp256k1::new();
let secret_key = SecretKey::from_slice(&hex::decode(private_key)?)?;
let message = Message::from_digest_slice(&self.hash()?)?;
let signature = secp.sign_ecdsa(&message, &secret_key);
Ok(signature)
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_hash() {
let commit = L2TxListsCommit {
tx_list_bytes: vec![1, 2, 3, 4, 5],
parent_meta_hash: [0u8; 32],
block_height: 1,
};

let hash_result = commit.hash();
assert!(hash_result.is_ok());
let hash = hash_result.unwrap();
assert_eq!(hash.len(), 32);
}

#[test]
fn test_sign() {
let commit = L2TxListsCommit {
tx_list_bytes: vec![1, 2, 3, 4, 5],
parent_meta_hash: [0u8; 32],
block_height: 1,
};

let private_key = "c87509a1c067bbde78beb793e6fa950b8d9c7f7bd5a8b16bf0d3a1a5b9bdfd3b";
let sign_result = commit.sign(private_key);
assert!(sign_result.is_ok());

let signature = sign_result.unwrap();
let secp = Secp256k1::new();
let public_key = SecretKey::from_slice(&hex::decode(private_key).unwrap())
.unwrap()
.public_key(&secp);
let message = Message::from_digest_slice(&commit.hash().unwrap()).unwrap();
assert!(secp.verify_ecdsa(&message, &signature, &public_key).is_ok());
}
}
1 change: 1 addition & 0 deletions Node/src/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod commit;
pub mod config;
pub mod rpc_client;
pub mod rpc_server;
2 changes: 2 additions & 0 deletions tools/tx_spammer/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
web3
python-dotenv
84 changes: 84 additions & 0 deletions tools/tx_spammer/tx_spammer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
r"""
This script is used to spam transactions on the Taiko network. It reads the private key and recipient address from a .env file,
connects to the Taiko network, and sends a specified number of transactions to the recipient address.
Setup:
1. Create a virtual environment:
python -m venv venv
2. Activate the virtual environment:
- On Windows: venv\Scripts\activate
- On macOS/Linux: source venv/bin/activate
3. Install the required dependencies:
pip install -r requirements.txt
4. Create a .env file in the tools/tx_spammer directory with the following content:
PRIVATE_KEY=<your_private_key>
RECIPIENT_ADDRESS=<recipient_address>
5. Run the script:
python tx_spammer.py [--count COUNT] [--amount AMOUNT]
CLI Parameters:
--count: Number of transactions to send (default: 1)
--amount: Amount of ETH to send per transaction (default: 0.006)
"""



import time
from web3 import Web3
import os
from dotenv import load_dotenv
import argparse

# Load environment variables from .env file
load_dotenv()

private_key = os.getenv('PRIVATE_KEY')
if not private_key:
raise Exception("Environment variable PRIVATE_KEY not set")

recipient = os.getenv('RECIPIENT_ADDRESS')
if not recipient:
raise Exception("Environment variable RECIPIENT_ADDRESS not set")

parser = argparse.ArgumentParser(description='Spam transactions on the Taiko network.')
parser.add_argument('--count', type=int, default=1, help='Number of transactions to send')
parser.add_argument('--amount', type=float, default=0.006, help='Amount of ETH to send per transaction')
args = parser.parse_args()

# Connect to the Taiko network
w3 = Web3(Web3.HTTPProvider('https://RPC.helder.taiko.xyz'))

# Check if connected
if not w3.is_connected():
raise Exception("Failed to connect to the Taiko network")

# Get the account from the private key
account = w3.eth.account.from_key(private_key)
amount = w3.to_wei(args.amount, 'ether')

def send_transaction(nonce : int):
tx = {
'nonce': nonce,
'to': recipient,
'value': amount,
'gas': 21000,
'gasPrice': w3.to_wei('10', 'gwei'),
'chainId': w3.eth.chain_id
}
print(f'Sending transaction: {tx}')
signed_tx = w3.eth.account.sign_transaction(tx, private_key)
tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction)
print(f'Transaction sent: {tx_hash.hex()}')

def spam_transactions(count):
nonce = w3.eth.get_transaction_count(account.address)
for _ in range(count):
send_transaction(nonce)
nonce += 1
time.sleep(0.01) # Add a delay to avoid nonce issues

spam_transactions(args.count)

0 comments on commit 0e30434

Please sign in to comment.