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: Gas Utils for L1 operations #9834

Merged
merged 56 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
7dca6df
feat: Gas Utils for L1 operations
spypsy Nov 8, 2024
8a0edaa
undo irrelevant change
spypsy Nov 8, 2024
fdfc143
update some logging
spypsy Nov 8, 2024
df22c32
Merge branch 'master' into spy/gas-utils
spypsy Nov 8, 2024
347d750
add e2e test
spypsy Nov 11, 2024
d01a316
add to E2E test config
spypsy Nov 11, 2024
78f8fb2
Merge branch 'master' into spy/gas-utils
spypsy Nov 11, 2024
427c836
rm old import
spypsy Nov 11, 2024
1adc20e
small fixes
spypsy Nov 13, 2024
b481eb2
rm pk logging
spypsy Nov 13, 2024
13d731a
formatting & test issues
spypsy Nov 13, 2024
e688b8d
formatting
spypsy Nov 13, 2024
b280ed4
don't fail script when ADDRESS & pk are unset
spypsy Nov 13, 2024
58bcc71
remove logs
spypsy Nov 13, 2024
2261352
update default private_key assignment in validator.sh
spypsy Nov 13, 2024
7092327
use const for WEI
spypsy Nov 13, 2024
1b4c8c3
skip PRIVATE_KEY assignment
spypsy Nov 13, 2024
31449f7
WIP: PR fixes
spypsy Nov 14, 2024
9af92ea
Merge branch 'master' into spy/gas-utils
spypsy Nov 14, 2024
d066d51
refactor GasUtils
spypsy Nov 18, 2024
f96b1d8
simplify acc & wallets
spypsy Nov 18, 2024
e18c4f9
bump priorityFee on retries
spypsy Nov 18, 2024
f853f21
configs
spypsy Nov 18, 2024
569bf2d
Merge branch 'master' into spy/gas-utils
spypsy Nov 19, 2024
b3223d7
rename to L1TxUtils
spypsy Nov 19, 2024
47f15a4
don't use 0x
spypsy Nov 19, 2024
03fbf79
send contract deployments to null
spypsy Nov 19, 2024
280c9a7
fix publisher tests
spypsy Nov 19, 2024
0b45fe6
fix getNodeInfo test
spypsy Nov 19, 2024
bb5505b
Merge branch 'master' into spy/gas-utils
spypsy Nov 19, 2024
653a083
split sendTx & monitorTx for separate use
spypsy Nov 19, 2024
c15d6b1
calc nonce in monitor function
spypsy Nov 19, 2024
9508cb7
fix null-check
spypsy Nov 19, 2024
81c03e7
Merge branch 'master' into spy/gas-utils
spypsy Nov 20, 2024
d80ece6
remove from e2e config
spypsy Nov 20, 2024
47edcd8
temp fix integration publisher test
spypsy Nov 20, 2024
d1fa404
temp fix integration publisher test
spypsy Nov 20, 2024
09339a4
some PR fixes
spypsy Nov 21, 2024
a331d9e
use default-defined value
spypsy Nov 21, 2024
1b169b4
more PR fixes
spypsy Nov 21, 2024
8818d1f
10% min fee bump, ensure test sends replacement tx
spypsy Nov 22, 2024
60afdea
merge conflicts
spypsy Nov 22, 2024
2c4858d
Merge branch 'master' into spy/gas-utils
spypsy Nov 25, 2024
c2338d0
Merge branch 'master' into spy/gas-utils
spypsy Nov 26, 2024
34170d1
undo submodule changes
spypsy Nov 26, 2024
3d46d87
fix get-node-info opts
spypsy Nov 27, 2024
af2d3e6
requesting info from node, not pxe
spypsy Nov 27, 2024
4ab1d4b
Merge branch 'master' into spy/gas-utils
spypsy Nov 29, 2024
0834d50
More PR fixes
spypsy Nov 29, 2024
0c20390
fix await
spypsy Nov 29, 2024
5fd231b
add cheat codes
spypsy Dec 2, 2024
a17a0ae
expect two error calls
spypsy Dec 2, 2024
0c84a64
update l1-publisher tests
spypsy Dec 2, 2024
de03935
add priorityFee to maxFeePerGas calculation, retry fetching l1 tx
spypsy Dec 3, 2024
e62ba9c
fix priorityFee addition, add gas calculationt ests
spypsy Dec 4, 2024
e4cc25f
Merge branch 'master' into spy/gas-utils
spypsy Dec 4, 2024
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
1 change: 1 addition & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"asyncify",
"auditability",
"authwit",
"Automine",
"autonat",
"autorun",
"awslogs",
Expand Down
4 changes: 2 additions & 2 deletions spartan/aztec-network/files/config/config-prover-env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ set -eu

# Pass the bootnode url as an argument
# Ask the bootnode for l1 contract addresses
output=$(node --no-warnings /usr/src/yarn-project/aztec/dest/bin/index.js get-node-info -u $1)
output=$(node --no-warnings /usr/src/yarn-project/aztec/dest/bin/index.js get-node-info --node-url $1)

echo "$output"

Expand All @@ -20,7 +20,7 @@ governance_proposer_address=$(echo "$output" | grep -oP 'GovernanceProposer Addr
governance_address=$(echo "$output" | grep -oP 'Governance Address: \K0x[a-fA-F0-9]{40}')

# Write the addresses to a file in the shared volume
cat <<EOF > /shared/contracts/contracts.env
cat <<EOF >/shared/contracts/contracts.env
export BOOTSTRAP_NODES=$boot_node_enr
export ROLLUP_CONTRACT_ADDRESS=$rollup_address
export REGISTRY_CONTRACT_ADDRESS=$registry_address
Expand Down
6 changes: 2 additions & 4 deletions spartan/aztec-network/files/config/config-validator-env.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
#!/bin/bash
set -eu


# Pass the bootnode url as an argument
# Ask the bootnode for l1 contract addresses
output=$(node --no-warnings /usr/src/yarn-project/aztec/dest/bin/index.js get-node-info -u $1)
output=$(node --no-warnings /usr/src/yarn-project/aztec/dest/bin/index.js get-node-info --node-url $1)

echo "$output"

Expand All @@ -25,9 +24,8 @@ governance_address=$(echo "$output" | grep -oP 'Governance Address: \K0x[a-fA-F0
INDEX=$(echo $POD_NAME | awk -F'-' '{print $NF}')
private_key=$(jq -r ".[$INDEX]" /app/config/keys.json)


# Write the addresses to a file in the shared volume
cat <<EOF > /shared/contracts/contracts.env
cat <<EOF >/shared/contracts/contracts.env
export BOOTSTRAP_NODES=$boot_node_enr
export ROLLUP_CONTRACT_ADDRESS=$rollup_address
export REGISTRY_CONTRACT_ADDRESS=$registry_address
Expand Down
24 changes: 24 additions & 0 deletions yarn-project/aztec-node/src/aztec-node/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import {
type L1_TO_L2_MSG_TREE_HEIGHT,
type NOTE_HASH_TREE_HEIGHT,
type NULLIFIER_TREE_HEIGHT,
type NodeInfo,
type NullifierLeafPreimage,
type PUBLIC_DATA_TREE_HEIGHT,
type PrivateLog,
Expand Down Expand Up @@ -237,6 +238,29 @@ export class AztecNodeService implements AztecNode {
return Promise.resolve(this.p2pClient.isReady() ?? false);
}

public async getNodeInfo(): Promise<NodeInfo> {
const [nodeVersion, protocolVersion, chainId, enr, contractAddresses, protocolContractAddresses] =
await Promise.all([
this.getNodeVersion(),
this.getVersion(),
this.getChainId(),
this.getEncodedEnr(),
this.getL1ContractAddresses(),
this.getProtocolContractAddresses(),
]);

const nodeInfo: NodeInfo = {
nodeVersion,
l1ChainId: chainId,
protocolVersion,
enr,
l1ContractAddresses: contractAddresses,
protocolContractAddresses: protocolContractAddresses,
};

return nodeInfo;
}

/**
* Get a block specified by its number.
* @param number - The block number being requested.
Expand Down
3 changes: 1 addition & 2 deletions yarn-project/aztec.js/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ export { ContractDeployer } from './deployment/index.js';
export {
AnvilTestWatcher,
CheatCodes,
EthCheatCodes,
L1FeeJuicePortalManager,
L1ToL2TokenPortalManager,
L1TokenManager,
Expand Down Expand Up @@ -165,7 +164,7 @@ export { elapsed } from '@aztec/foundation/timer';
export { type FieldsOf } from '@aztec/foundation/types';
export { fileURLToPath } from '@aztec/foundation/url';

export { deployL1Contract, deployL1Contracts, type DeployL1Contracts } from '@aztec/ethereum';
export { type DeployL1Contracts, EthCheatCodes, deployL1Contract, deployL1Contracts } from '@aztec/ethereum';

// Start of section that exports public api via granular api.
// Here you *can* do `export *` as the granular api defacto exports things explicitly.
Expand Down
247 changes: 1 addition & 246 deletions yarn-project/aztec.js/src/utils/cheat_codes.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { type EpochProofClaim, type Note, type PXE } from '@aztec/circuit-types';
import { type AztecAddress, EthAddress, Fr } from '@aztec/circuits.js';
import { deriveStorageSlotInMap } from '@aztec/circuits.js/hash';
import { type L1ContractAddresses } from '@aztec/ethereum';
import { toBigIntBE, toHex } from '@aztec/foundation/bigint-buffer';
import { keccak256 } from '@aztec/foundation/crypto';
import { EthCheatCodes, type L1ContractAddresses } from '@aztec/ethereum';
import { createDebugLogger } from '@aztec/foundation/log';
import { RollupAbi } from '@aztec/l1-artifacts';

import fs from 'fs';
import {
type GetContractReturnType,
type Hex,
Expand Down Expand Up @@ -49,248 +46,6 @@ export class CheatCodes {
}
}

/**
* A class that provides utility functions for interacting with ethereum (L1).
*/
export class EthCheatCodes {
constructor(
/**
* The RPC URL to use for interacting with the chain
*/
public rpcUrl: string,
/**
* The logger to use for the eth cheatcodes
*/
public logger = createDebugLogger('aztec:cheat_codes:eth'),
) {}

async rpcCall(method: string, params: any[]) {
const paramsString = JSON.stringify(params);
const content = {
body: `{"jsonrpc":"2.0", "method": "${method}", "params": ${paramsString}, "id": 1}`,
method: 'POST',
headers: { 'Content-Type': 'application/json' },
};
return await (await fetch(this.rpcUrl, content)).json();
}

/**
* Get the auto mine status of the underlying chain
* @returns True if automine is on, false otherwise
*/
public async isAutoMining(): Promise<boolean> {
try {
const res = await this.rpcCall('anvil_getAutomine', []);
return res.result;
} catch (err) {
this.logger.error(`Calling "anvil_getAutomine" failed with:`, err);
}
return false;
}

/**
* Get the current blocknumber
* @returns The current block number
*/
public async blockNumber(): Promise<number> {
const res = await this.rpcCall('eth_blockNumber', []);
return parseInt(res.result, 16);
}

/**
* Get the current chainId
* @returns The current chainId
*/
public async chainId(): Promise<number> {
const res = await this.rpcCall('eth_chainId', []);
return parseInt(res.result, 16);
}

/**
* Get the current timestamp
* @returns The current timestamp
*/
public async timestamp(): Promise<number> {
const res = await this.rpcCall('eth_getBlockByNumber', ['latest', true]);
return parseInt(res.result.timestamp, 16);
}

/**
* Advance the chain by a number of blocks
* @param numberOfBlocks - The number of blocks to mine
* @returns The current chainId
*/
public async mine(numberOfBlocks = 1): Promise<void> {
const res = await this.rpcCall('hardhat_mine', [numberOfBlocks]);
if (res.error) {
throw new Error(`Error mining: ${res.error.message}`);
}
this.logger.verbose(`Mined ${numberOfBlocks} L1 blocks`);
}

/**
* Set the balance of an account
* @param account - The account to set the balance for
* @param balance - The balance to set
*/
public async setBalance(account: EthAddress, balance: bigint): Promise<void> {
const res = await this.rpcCall('anvil_setBalance', [account.toString(), toHex(balance)]);
if (res.error) {
throw new Error(`Error setting balance for ${account}: ${res.error.message}`);
}
this.logger.verbose(`Set balance for ${account} to ${balance}`);
}

/**
* Set the interval between blocks (block time)
* @param interval - The interval to use between blocks
*/
public async setBlockInterval(interval: number): Promise<void> {
const res = await this.rpcCall('anvil_setBlockTimestampInterval', [interval]);
if (res.error) {
throw new Error(`Error setting block interval: ${res.error.message}`);
}
this.logger.verbose(`Set L1 block interval to ${interval}`);
}

/**
* Set the next block timestamp
* @param timestamp - The timestamp to set the next block to
*/
public async setNextBlockTimestamp(timestamp: number): Promise<void> {
const res = await this.rpcCall('evm_setNextBlockTimestamp', [timestamp]);
if (res.error) {
throw new Error(`Error setting next block timestamp: ${res.error.message}`);
}
this.logger.verbose(`Set L1 next block timestamp to ${timestamp}`);
}

/**
* Set the next block timestamp and mines the block
* @param timestamp - The timestamp to set the next block to
*/
public async warp(timestamp: number | bigint): Promise<void> {
const res = await this.rpcCall('evm_setNextBlockTimestamp', [Number(timestamp)]);
if (res.error) {
throw new Error(`Error warping: ${res.error.message}`);
}
await this.mine();
this.logger.verbose(`Warped L1 timestamp to ${timestamp}`);
}

/**
* Dumps the current chain state to a file.
* @param fileName - The file name to dump state into
*/
public async dumpChainState(fileName: string): Promise<void> {
const res = await this.rpcCall('hardhat_dumpState', []);
if (res.error) {
throw new Error(`Error dumping state: ${res.error.message}`);
}
const jsonContent = JSON.stringify(res.result);
fs.writeFileSync(`${fileName}.json`, jsonContent, 'utf8');
this.logger.verbose(`Dumped state to ${fileName}`);
}

/**
* Loads the chain state from a file.
* @param fileName - The file name to load state from
*/
public async loadChainState(fileName: string): Promise<void> {
const data = JSON.parse(fs.readFileSync(`${fileName}.json`, 'utf8'));
const res = await this.rpcCall('hardhat_loadState', [data]);
if (res.error) {
throw new Error(`Error loading state: ${res.error.message}`);
}
this.logger.verbose(`Loaded state from ${fileName}`);
}

/**
* Load the value at a storage slot of a contract address on eth
* @param contract - The contract address
* @param slot - The storage slot
* @returns - The value at the storage slot
*/
public async load(contract: EthAddress, slot: bigint): Promise<bigint> {
const res = await this.rpcCall('eth_getStorageAt', [contract.toString(), toHex(slot), 'latest']);
return BigInt(res.result);
}

/**
* Set the value at a storage slot of a contract address on eth
* @param contract - The contract address
* @param slot - The storage slot
* @param value - The value to set the storage slot to
*/
public async store(contract: EthAddress, slot: bigint, value: bigint): Promise<void> {
// for the rpc call, we need to change value to be a 32 byte hex string.
const res = await this.rpcCall('hardhat_setStorageAt', [contract.toString(), toHex(slot), toHex(value, true)]);
if (res.error) {
throw new Error(`Error setting storage for contract ${contract} at ${slot}: ${res.error.message}`);
}
this.logger.verbose(`Set L1 storage for contract ${contract} at ${slot} to ${value}`);
}

/**
* Computes the slot value for a given map and key.
* @param baseSlot - The base slot of the map (specified in Aztec.nr contract)
* @param key - The key to lookup in the map
* @returns The storage slot of the value in the map
*/
public keccak256(baseSlot: bigint, key: bigint): bigint {
// abi encode (removing the 0x) - concat key and baseSlot (both padded to 32 bytes)
const abiEncoded = toHex(key, true).substring(2) + toHex(baseSlot, true).substring(2);
return toBigIntBE(keccak256(Buffer.from(abiEncoded, 'hex')));
}

/**
* Send transactions impersonating an externally owned account or contract.
* @param who - The address to impersonate
*/
public async startImpersonating(who: EthAddress | Hex): Promise<void> {
const res = await this.rpcCall('hardhat_impersonateAccount', [who.toString()]);
if (res.error) {
throw new Error(`Error impersonating ${who}: ${res.error.message}`);
}
this.logger.verbose(`Impersonating ${who}`);
}

/**
* Stop impersonating an account that you are currently impersonating.
* @param who - The address to stop impersonating
*/
public async stopImpersonating(who: EthAddress | Hex): Promise<void> {
const res = await this.rpcCall('hardhat_stopImpersonatingAccount', [who.toString()]);
if (res.error) {
throw new Error(`Error when stopping the impersonation of ${who}: ${res.error.message}`);
}
this.logger.verbose(`Stopped impersonating ${who}`);
}

/**
* Set the bytecode for a contract
* @param contract - The contract address
* @param bytecode - The bytecode to set
*/
public async etch(contract: EthAddress, bytecode: `0x${string}`): Promise<void> {
const res = await this.rpcCall('hardhat_setCode', [contract.toString(), bytecode]);
if (res.error) {
throw new Error(`Error setting bytecode for ${contract}: ${res.error.message}`);
}
this.logger.verbose(`Set bytecode for ${contract} to ${bytecode}`);
}

/**
* Get the bytecode for a contract
* @param contract - The contract address
* @returns The bytecode for the contract
*/
public async getBytecode(contract: EthAddress): Promise<`0x${string}`> {
const res = await this.rpcCall('eth_getCode', [contract.toString(), 'latest']);
return res.result;
}
}

/** Cheat codes for the L1 rollup contract. */
export class RollupCheatCodes {
private client: WalletClient & PublicClient;
Expand Down
Loading
Loading