Skip to content

Commit

Permalink
add propose block script
Browse files Browse the repository at this point in the history
  • Loading branch information
Keszey Dániel authored and Keszey Dániel committed Jul 19, 2024
1 parent ca4a6e6 commit 93c26f7
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 0 deletions.
2 changes: 2 additions & 0 deletions packages/protocol/deployments/local_deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ participants:
el_image: ghcr.io/paradigmxyz/reth # We can use custom image, (remote, e.g.: ethpandaops/reth:main-9c0bc84 or locally: taiko_reth)
cl_type: teku
cl_image: consensys/teku:latest
network_params:
network_id: '160010'
```

#### 1.1 Local reth-based network
Expand Down
78 changes: 78 additions & 0 deletions packages/protocol/scripts/L2_txn_simulation/ProposeBlock.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// SPDX-License-Identifier: MIT
// _____ _ _ _ _
// |_ _|_ _(_) |_____ | | __ _| |__ ___
// | |/ _` | | / / _ \ | |__/ _` | '_ (_-<
// |_|\__,_|_|_\_\___/ |____\__,_|_.__/__/

pragma solidity ^0.8.20;

import "forge-std/Script.sol";
import "forge-std/console2.sol";

import "../../contracts/L1/TaikoL1.sol";

contract ProposeBlock is Script {
address public taikoL1Address = 0x9fCF7D13d10dEdF17d0f24C62f0cf4ED462f65b7;//address(0);// TaikoL1 proxy address -> Get from the deployment
address sender = 0x8943545177806ED17B9F23F0a21ee5948eCaa776; // With pre-generated eth

function run() external {

require(taikoL1Address != address(0), "based operator not set");

vm.startBroadcast();

bytes[] memory txLists = new bytes[](1);
// The L2 chainId with which i encoded the TXNs were 167011
// THe nonce was 0
bytes memory firstAddressSendingNonce0 = hex"02f87683028c6380843b9aca00847735940083030d4094f93ee4cf8c6c40b329b0c0626f28333c132cf24188016345785d8a000080c080a08f0f52d943504cecea0d6ce317c2fde8b0c27b1e449d85fcf98ccd2f50ac804ba04d5d56356518c1de0c1ece644a8a2fe64e6cc136cd8db0a21a21f72c167353c6";
bytes memory secondAddressSendingNonce0 = hex"02f87683028c6380843b9aca00847735940083030d4094f93ee4cf8c6c40b329b0c0626f28333c132cf24188016345785d8a000080c080a0622e7060e09afd2100784bdc88ebb838729128bb6eb40f8b7f458430d56dafd4a006fe5d1a466788f941020a2278860c3f2642e44108c666ecd25b30d1b2f7a420";
bytes memory thirdAddressSendingNonce0 = hex"02f87683028c6380843b9aca00847735940083030d4094f93ee4cf8c6c40b329b0c0626f28333c132cf24188016345785d8a000080c001a0558488f3af91777c382d2ab6ac3507f5d6b906431534193c1a45cc2a08b2825ea0495efd571c9ea5a5290f10efaa219f8c31b4e714745737c4e019df76f7a6df4b";

// The outcome of the above is the rlp encoded list (not concatenated but RLP encoded with: https://toolkit.abdk.consulting/ethereum#key-to-address,rlp)
txLists[0] = hex"f90171b87902f87683028c6280843b9aca00847735940083030d4094f93ee4cf8c6c40b329b0c0626f28333c132cf241880de0b6b3a764000080c080a07f983645ddf8365d14e5fb4e3b07c19fe31e23edd9ee4a737388acc2da7e64a3a072a56043512806a6de5f66f28bb659236eea41c9d66db8493f436804c42723d3b87902f87683028c6280843b9aca00847735940083030d4094f93ee4cf8c6c40b329b0c0626f28333c132cf241880de0b6b3a764000080c001a030911ab2ebf76f1e1bfe00d721207d929053efb051d50708a10dd9f66f84bacba07705a7cdb86ff00aa8c131ef3c4cb2ea2f2f4730d93308f1afbb94a04c1c9ae9b87902f87683028c6280843b9aca00847735940083030d4094f93ee4cf8c6c40b329b0c0626f28333c132cf241880de0b6b3a764000080c001a07da8dfb5bc3b7b353f9614bcd83733168500d1e06f2bcdac761cc54c85847e6aa03b041b0605e86aa379ff0f58a60743da411dfd1a9d4f1d18422a862f67a57fee";

bytes32 txListHash = keccak256(txLists[0]); //Since we not using Blobs, we need this

// MetaData related
bytes[] memory metasEncoded = new bytes[](1);
TaikoData.BlockMetadata memory meta;
console2.log(txLists[0].length);

meta = createBlockMetaDataForFirstBlockDebug(sender, 1, uint64(block.timestamp), uint24(txLists[0].length), txListHash);

metasEncoded[0] = abi.encode(meta);

TaikoL1(taikoL1Address).proposeBlock{value: 0.1 ether }(metasEncoded, txLists);

vm.stopBroadcast();
}

function createBlockMetaDataForFirstBlockDebug(
address coinbase,
uint64 l2BlockNumber,
uint64 unixTimestamp,
uint24 txListByteSize,
bytes32 txListHash
)
internal
returns (TaikoData.BlockMetadata memory meta)
{
meta.blockHash = 0xab80a9c4daa571aa308e967c9a6b4bf21ba8842d95d73d28be112b6fe0618e7c; // Randomly set it to smth

//TaikoData.Block memory parentBlock = L1.getBlock(l2BlockNumber - 1);
meta.parentMetaHash = 0x0000000000000000000000000000000000000000000000000000000000000000; // This is the genesis block's metaHash
meta.parentBlockHash = 0xdf90a9c4daa571aa308e967c9a6b4bf21ba8842d95d73d28be112b6fe0618e8c; // This is the genesis block's blockhash
meta.l1Hash = blockhash(30); //L1 private network's L1 blockheight, submit this block between 30 and 30+128 blcok of L1.

Check failure on line 65 in packages/protocol/scripts/L2_txn_simulation/ProposeBlock.s.sol

View workflow job for this annotation

GitHub Actions / codespell

blcok ==> block
meta.difficulty = block.prevrandao;
meta.blobHash = txListHash;
meta.coinbase = coinbase;
meta.l2BlockNumber = l2BlockNumber;
meta.gasLimit = 15_000_000;
meta.l1StateBlockNumber = uint32(30); // Submit this block between 30 and 30+128 blcok of L1.

Check failure on line 71 in packages/protocol/scripts/L2_txn_simulation/ProposeBlock.s.sol

View workflow job for this annotation

GitHub Actions / codespell

blcok ==> block
meta.timestamp = unixTimestamp;

meta.txListByteOffset = 0;
meta.txListByteSize = txListByteSize; // Corresponding txn list byte size
meta.blobUsed = false;
}
}
50 changes: 50 additions & 0 deletions packages/protocol/scripts/L2_txn_simulation/createL2Txn.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from web3 import Web3
from eth_abi import encode
import argparse

RPC_URL_L2 = 'http://127.0.0.1:8545' # Anything is fine for now as long as we dont have the L2 network, but if we have we can automate nonce and gas settings
w3_taiko_l2 = Web3(Web3.HTTPProvider(RPC_URL_L2))

# Some pre-loaded ETH addresses from Kurtosis private network (NO secret, no harm to use for private testnets!)
sender_addresses = ['0x8943545177806ED17B9F23F0a21ee5948eCaa776', '0xE25583099BA105D9ec0A67f5Ae86D90e50036425', '0x614561D2d143621E126e87831AEF287678B442b8']
sender_pks = ['bcdf20249abf0ed6d944c0288fad489e33f66b3960d9e6229c1cd214ed3bbe31', '39725efee3fb28614de3bacaffe4cc4bd8c436257e2c8bb887c4b5c4be45e76d', '53321db7c1e331d93a11a41d16f004d7ff63972ec8ec7c25db329728ceeb1710']

receiver = '0xf93Ee4Cf8c6c40b329b0c0626F28333c132CF241' # This address also has pre-loaded ETH addresses

parser = argparse.ArgumentParser()

parser.add_argument("-n", "--nonce", help="collective nonce",
type=int, required=True)
parser.add_argument("-c", "--chainid", help="l2 chainId",
type=int, required=True)

transaction_list = []

if __name__ == "__main__":
args = parser.parse_args()
nonce = args.nonce
chainId = args.chainid

# Build the new tx list
idx = 0
for sender in sender_addresses:
# Build the tx
transaction = {
'chainId': chainId,
'from': sender,
'to': receiver,
'value': w3_taiko_l2.to_wei('1', 'ether'),
'nonce': nonce, # later we can use something like: w3_taiko_l2.eth.get_transaction_count(address1),
'gas': 200000,
'maxFeePerGas': 2000000000, # w3_taiko_l2.eth.gas_price or something
'maxPriorityFeePerGas': 1000000000,
}

# 2. Sign tx with a private key
signed_txn = w3_taiko_l2.eth.account.sign_transaction(transaction, sender_pks[idx])

# Most probably we need to zlib + rlp encode transactions not only just "concatenate"
print("Txn ",idx, " bytes:")
print(signed_txn.rawTransaction.hex())
transaction_list.append(signed_txn)
idx += 1
46 changes: 46 additions & 0 deletions packages/protocol/scripts/L2_txn_simulation/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Create / simulate L2 transactions

In order to test the L2 node execution hook functionality, we need create valid L2 transactions and submit those to TaikoL1 - where a hook will be built in, to listen the proposeBlock and execute those transactions. This folder is to create L2 transactions (using the same pre-funded accounts Kurtosis is setting up by default) and submit it to our "L1" while using the local taiko_reth image as the EL.

## Prerequisites

Prerequisites can also be found in `deployments/local_deployment.md` file.

1. Testnet up and running:
```shell
kurtosis run github.com/ethpandaops/ethereum-package --args-file YOUR_PATH_TO_NETWORK_CONFIG/network_params.yaml
```

2. Main contracts deployed:
```shell
forge script --rpc-url http://127.0.0.1:PORT scripts/DeployL1Locally.s.sol -vvvv --broadcast --private-key PK --legacy
```

## 1. Create and print L2 transactions ("off-chain")

Run script to gather 3 ether transactions, and print them out. `-n` flag stands for the nonce, and `-c` is for the L2 chainId.

```shell
$ python3 createL2Txns.py -n <CORRECT_L2_NONCE> -c <CORRECT_L2_CHAINID>
```

## 2. Prepare the script with proper data and fire away the L1 transaction

Edit the `ProposeBlock.s.sol` file to to set the valid `basedOperatorAddress` and also add the above generated 3 signed transactions (already in the `ProposeBlock.s.sol` file, not needed to run and add them, unless the network `id` or `nonce` is different), then fire away the L1 transaction with the script below:

```shell
$ forge script --rpc-url http://127.0.0.1:YOUR_PORT scripts/L2_txn_simulation/ProposeBlock.s.sol -vvvv --broadcast --private-key <YOUR_PRIVATE_KEY> --legacy
```

## 3. In case of TXN failure, you can get the error via the debug trace transaction RPC call

Command

```shell
curl http://127.0.0.1:YOUR_PORT \
-X POST \
-H "Content-Type: application/json" \
--data '{"method":"debug_traceTransaction","params":["YOUR_TXN_HASH", {"tracer": "callTracer"}], "id":1,"jsonrpc":"2.0"}'
```


0 comments on commit 93c26f7

Please sign in to comment.