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

Add 'blessed' transactions which are exempt from gas price rules #1072

Merged
merged 2 commits into from
Jun 24, 2024
Merged
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
10 changes: 7 additions & 3 deletions evm_scilla_js_tests/test/rpc/eth_estimateGas.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ethers } from "hardhat";
import sendJsonRpcRequest from "../../helpers/JsonRpcHelper";
import {assert} from "chai";

@@ -6,13 +7,14 @@ const METHOD = "eth_estimateGas";
// TODO: When/if we want to, assert the gas price so as to check the gas calculations.
describe(`Calling ${METHOD} #parallel`, function () {
it("should accept estimateGas with a block tag @block-1", async function () {
const [signer] = await ethers.getSigners();
await sendJsonRpcRequest(
METHOD,
2,
[
{
data: "0x60806040526040516101a63803806101a68339818101604052810190610025919061006d565b806000819055505061009a565b600080fd5b6000819050919050565b61004a81610037565b811461005557600080fd5b50565b60008151905061006781610041565b92915050565b60006020828403121561008357610082610032565b5b600061009184828501610058565b91505092915050565b60fe806100a86000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80638381f58a146037578063ef5fb05b146051575b600080fd5b603d6059565b6040516048919060af565b60405180910390f35b6057605f565b005b60005481565b7f6907508952f1c853768d61a5d281b8e23ad78ab8503ddc9404e21d6affade6d3600054604051608e919060af565b60405180910390a1565b6000819050919050565b60a9816098565b82525050565b600060208201905060c2600083018460a2565b9291505056fea26469706673582212203151b21ab4ce0f1e6e7333acb907eae279eb97b81e4926925139a34fe623454e64736f6c63430008130033000000000000000000000000000000000000000000000000000000000000002a",
from: "0xf0cb24ac66ba7375bf9b9c4fa91e208d9eaabd2e"
from: signer.address,
},
"pending"
],
@@ -27,13 +29,14 @@ describe(`Calling ${METHOD} #parallel`, function () {
});

it("should accept estimateGas without a block tag @block-1", async function () {
const [signer] = await ethers.getSigners();
await sendJsonRpcRequest(
METHOD,
1,
[
{
data: "0x60806040526040516101a63803806101a68339818101604052810190610025919061006d565b806000819055505061009a565b600080fd5b6000819050919050565b61004a81610037565b811461005557600080fd5b50565b60008151905061006781610041565b92915050565b60006020828403121561008357610082610032565b5b600061009184828501610058565b91505092915050565b60fe806100a86000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80638381f58a146037578063ef5fb05b146051575b600080fd5b603d6059565b6040516048919060af565b60405180910390f35b6057605f565b005b60005481565b7f6907508952f1c853768d61a5d281b8e23ad78ab8503ddc9404e21d6affade6d3600054604051608e919060af565b60405180910390a1565b6000819050919050565b60a9816098565b82525050565b600060208201905060c2600083018460a2565b9291505056fea26469706673582212203151b21ab4ce0f1e6e7333acb907eae279eb97b81e4926925139a34fe623454e64736f6c63430008130033000000000000000000000000000000000000000000000000000000000000002a",
from: "0xf0cb24ac66ba7375bf9b9c4fa91e208d9eaabd2e"
from: signer.address,
}
],
(result, status) => {
@@ -47,13 +50,14 @@ describe(`Calling ${METHOD} #parallel`, function () {
});

xit("should not accept estimateGas with an invalid block tag @block-1", async function () {
const [signer] = await ethers.getSigners();
await sendJsonRpcRequest(
METHOD,
2,
[
{
data: "0x60806040526040516101a63803806101a68339818101604052810190610025919061006d565b806000819055505061009a565b600080fd5b6000819050919050565b61004a81610037565b811461005557600080fd5b50565b60008151905061006781610041565b92915050565b60006020828403121561008357610082610032565b5b600061009184828501610058565b91505092915050565b60fe806100a86000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80638381f58a146037578063ef5fb05b146051575b600080fd5b603d6059565b6040516048919060af565b60405180910390f35b6057605f565b005b60005481565b7f6907508952f1c853768d61a5d281b8e23ad78ab8503ddc9404e21d6affade6d3600054604051608e919060af565b60405180910390a1565b6000819050919050565b60a9816098565b82525050565b600060208201905060c2600083018460a2565b9291505056fea26469706673582212203151b21ab4ce0f1e6e7333acb907eae279eb97b81e4926925139a34fe623454e64736f6c63430008130033000000000000000000000000000000000000000000000000000000000000002a",
from: "0xf0cb24ac66ba7375bf9b9c4fa91e208d9eaabd2e"
from: signer.address,
},
"fish"
],
2 changes: 2 additions & 0 deletions z2/src/converter.rs
Original file line number Diff line number Diff line change
@@ -30,6 +30,7 @@ use zilliqa::{
contracts,
crypto::{Hash, SecretKey},
db::Db,
exec::BaseFeeCheck,
inspector,
message::{Block, BlockHeader, QuorumCertificate, Vote},
schnorr,
@@ -137,6 +138,7 @@ pub async fn convert_persistence(
0,
BlockHeader::default(),
inspector::noop(),
BaseFeeCheck::Ignore,
)?;
if !result.is_success() {
return Err(anyhow!("setting stake failed: {result:?}"));
2 changes: 1 addition & 1 deletion zilliqa/Cargo.toml
Original file line number Diff line number Diff line change
@@ -61,7 +61,7 @@ prost = "0.12.6"
rand = "0.8.5"
rand_chacha = "0.3.1"
rand_core = "0.6.4"
revm = { version = "9.0.0", features = ["optional_balance_check"] }
revm = { version = "9.0.0", features = ["optional_no_base_fee"] }
revm-inspectors = { git = "https://github.com/paradigmxyz/evm-inspectors.git", rev = "5c47bc8", features = ["js-tracer"] }
rusqlite = { version = "0.31.0", features = ["bundled", "trace"] }
serde = { version = "1.0.203", features = ["derive", "rc"] }
46 changes: 38 additions & 8 deletions zilliqa/src/exec.rs
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ use std::{
sync::{Arc, MutexGuard},
};

use alloy_primitives::{Address, U256};
use alloy_primitives::{hex, Address, U256};
use anyhow::{anyhow, Result};
use bytes::Bytes;
use eth_trie::{EthTrie, Trie};
@@ -306,6 +306,13 @@ const SCILLA_INVOKE_RUNNER: ScillaGas = ScillaGas(300);

const SPEC_ID: SpecId = SpecId::SHANGHAI;

pub enum BaseFeeCheck {
/// Transaction gas price will be validated to be at least the block gas price.
Validate,
/// Transaction gas price will not be validated.
Ignore,
}

impl State {
/// Used primarily during genesis to set up contracts for chain functionality.
/// If override_address address is set, forces contract deployment to that addess.
@@ -317,14 +324,15 @@ impl State {
let (ResultAndState { result, mut state }, ..) = self.apply_transaction_evm(
Address::ZERO,
None,
self.gas_price,
0,
self.block_gas_limit,
0,
creation_bytecode,
None,
0,
BlockHeader::genesis(Hash::ZERO),
inspector::noop(),
BaseFeeCheck::Ignore,
)?;

match result {
@@ -367,6 +375,7 @@ impl State {
chain_id: u64,
current_block: BlockHeader,
inspector: I,
base_fee_check: BaseFeeCheck,
) -> Result<(ResultAndState, Box<Env>)> {
let mut evm = Evm::builder()
.with_db(self)
@@ -391,11 +400,10 @@ impl State {
.append_handler_register(inspector_handle_register)
.modify_cfg_env(|c| {
c.chain_id = chain_id;
// We disable the balance check (which ensures the from account's balance is greater than the
// transaction's `gas_price * gas_limit`), because Scilla transactions are often submitted with
// overly high `gas_limit`s. This is probably because there is no gas estimation feature for Scilla
// transactions.
c.disable_balance_check = true;
c.disable_base_fee = match base_fee_check {
BaseFeeCheck::Validate => false,
BaseFeeCheck::Ignore => true,
};
})
.with_tx_env(TxEnv {
caller: from_addr.0.into(),
@@ -480,6 +488,8 @@ impl State {
let from_addr = txn.signer;
info!(?hash, ?txn, "executing txn");

let blessed = BLESSED_TRANSACTIONS.contains(&hash);

let txn = txn.tx.into_transaction();
if let Transaction::Zilliqa(txn) = txn {
let (result, state) =
@@ -500,6 +510,11 @@ impl State {
chain_id,
current_block,
inspector,
if blessed {
BaseFeeCheck::Ignore
} else {
BaseFeeCheck::Validate
},
)?;

self.apply_delta_evm(&state)?;
@@ -781,6 +796,7 @@ impl State {
chain_id,
current_block,
inspector::noop(),
BaseFeeCheck::Validate,
)?;

match result {
@@ -818,6 +834,7 @@ impl State {
chain_id,
current_block,
inspector::noop(),
BaseFeeCheck::Validate,
)?;

match result {
@@ -854,14 +871,15 @@ impl State {
let (ResultAndState { result, .. }, ..) = self.apply_transaction_evm(
from_addr,
to_addr,
self.gas_price,
0,
self.block_gas_limit,
amount,
data,
None,
chain_id,
current_block,
inspector::noop(),
BaseFeeCheck::Ignore,
)?;

match result {
@@ -1557,3 +1575,15 @@ fn scilla_call(
state.take().expect("missing state"),
))
}

/// Blessed transactions bypass minimum gas price rules. These transactions have value to the network even at a lower
/// gas price, so we accept them anyway.
const BLESSED_TRANSACTIONS: [Hash; 1] = [
// Hash of the deployment transaction for the deterministic deployment proxy from
// https://github.com/Arachnid/deterministic-deployment-proxy. It is valuable to accept this transaction despite
// the low gas price, because it means the contract is deployed at the same address as other EVM-compatible chains.
// This means that contracts deployed using this proxy will be deployed to the same address as on other chains.
Hash(hex!(
"eddf9e61fb9d8f5111840daef55e5fde0041f5702856532cdbb5a02998033d26"
JamesHinshelwood marked this conversation as resolved.
Show resolved Hide resolved
)),
];
7 changes: 4 additions & 3 deletions zilliqa/src/state.rs
Original file line number Diff line number Diff line change
@@ -13,8 +13,8 @@ use serde::{Deserialize, Serialize};
use sha3::{Digest, Keccak256};

use crate::{
cfg::ConsensusConfig, contracts, crypto, db::TrieStorage, inspector, message::BlockHeader,
scilla::Scilla, transaction::EvmGas,
cfg::ConsensusConfig, contracts, crypto, db::TrieStorage, exec::BaseFeeCheck, inspector,
message::BlockHeader, scilla::Scilla, transaction::EvmGas,
};

#[derive(Debug)]
@@ -118,14 +118,15 @@ impl State {
) = state.apply_transaction_evm(
Address::ZERO,
Some(contract_addr::DEPOSIT),
*config.gas_price,
0,
config.eth_block_gas_limit,
0,
data,
None,
0,
BlockHeader::default(),
inspector::noop(),
BaseFeeCheck::Ignore,
)?;
if !result.is_success() {
return Err(anyhow!("setting stake failed: {result:?}"));
2 changes: 1 addition & 1 deletion zilliqa/tests/it/consensus.rs
Original file line number Diff line number Diff line change
@@ -347,7 +347,7 @@ async fn dynamic_cross_shard_link_creation(mut network: Network) {
// Then fund the shard 1 wallet on shard 2
let xfer_hash = shard_2_wallet
.send_transaction(
TransactionRequest::pay(shard_1_wallet.address(), 100_000_000_000_000u64),
TransactionRequest::pay(shard_1_wallet.address(), 100_000_000_000_000_000_000u128),
None,
)
.await
50 changes: 49 additions & 1 deletion zilliqa/tests/it/eth.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use std::{fmt::Debug, ops::DerefMut};

use alloy_primitives::Address;
use alloy_primitives::{hex, Address};
use ethabi::{ethereum_types::U64, Token};
use ethers::{
abi::FunctionExt,
core::types::Signature,
providers::{Middleware, Provider},
types::{
transaction::{
@@ -1146,3 +1147,50 @@ async fn get_accounts_with_extra_args(mut network: Network) {

assert!(result.is_err());
}

#[zilliqa_macros::test]
async fn deploy_deterministic_deployment_proxy(mut network: Network) {
let wallet = network.random_wallet().await;
let provider = wallet.inner();

let signer: H160 = "0x3fab184622dc19b6109349b94811493bf2a45362"
.parse()
.unwrap();

let gas_price = 100000000000u128;
let gas = 100000u128;

// Send the signer enough money to cover the deployment.
let tx = TransactionRequest::pay(signer, gas_price * gas);
send_transaction(&mut network, tx.into()).await;

// Transaction from https://github.com/Arachnid/deterministic-deployment-proxy.
let tx = TransactionRequest::new()
.nonce(0)
.gas_price(gas_price)
.gas(gas)
.value(0)
.data(hex!("604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3"));
let tx = TypedTransaction::Legacy(tx);
let signature = Signature {
r: hex!("2222222222222222222222222222222222222222222222222222222222222222").into(),
s: hex!("2222222222222222222222222222222222222222222222222222222222222222").into(),
v: 27,
};
let raw_tx = tx.rlp_signed(&signature);
let hash = provider
.send_raw_transaction(raw_tx)
.await
.unwrap()
.tx_hash();

let receipt = network.run_until_receipt(&wallet, hash, 100).await;

assert_eq!(receipt.from, signer);
assert_eq!(
receipt.contract_address.unwrap(),
"0x4e59b44847b379578588920ca78fbf26c0b4956c"
.parse()
.unwrap()
);
}