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

fix(eth-watch): Do not track for stm, only for diamond proxy #2080

Merged
merged 11 commits into from
May 30, 2024
2 changes: 1 addition & 1 deletion contracts
124 changes: 123 additions & 1 deletion core/lib/contracts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,8 @@ pub static PRE_BOOJUM_COMMIT_FUNCTION: Lazy<Function> = Lazy::new(|| {
});

pub static SET_CHAIN_ID_EVENT: Lazy<Event> = Lazy::new(|| {
let abi = r#"{
let abi = r#"
{
"anonymous": false,
"inputs": [
{
Expand Down Expand Up @@ -681,3 +682,124 @@ pub static SET_CHAIN_ID_EVENT: Lazy<Event> = Lazy::new(|| {
}"#;
serde_json::from_str(abi).unwrap()
});

// The function that was used in the pre-v23 versions of the contract to upgrade the diamond proxy.
pub static ADMIN_EXECUTE_UPGRADE_FUNCTION: Lazy<Function> = Lazy::new(|| {
let abi = r#"
{
"inputs": [
{
"components": [
{
"components": [
{
"internalType": "address",
"name": "facet",
"type": "address"
},
{
"internalType": "enum Diamond.Action",
"name": "action",
"type": "uint8"
},
{
"internalType": "bool",
"name": "isFreezable",
"type": "bool"
},
{
"internalType": "bytes4[]",
"name": "selectors",
"type": "bytes4[]"
}
],
"internalType": "struct Diamond.FacetCut[]",
"name": "facetCuts",
"type": "tuple[]"
},
{
"internalType": "address",
"name": "initAddress",
"type": "address"
},
{
"internalType": "bytes",
"name": "initCalldata",
"type": "bytes"
}
],
"internalType": "struct Diamond.DiamondCutData",
"name": "_diamondCut",
"type": "tuple"
}
],
"name": "executeUpgrade",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}"#;
serde_json::from_str(abi).unwrap()
});

// The function that is used in post-v23 chains to upgrade the chain
pub static ADMIN_UPGRADE_CHAIN_FROM_VERSION_FUNCTION: Lazy<Function> = Lazy::new(|| {
let abi = r#"
{
"inputs": [
{
"internalType": "uint256",
"name": "_oldProtocolVersion",
"type": "uint256"
},
{
"components": [
{
"components": [
{
"internalType": "address",
"name": "facet",
"type": "address"
},
{
"internalType": "enum Diamond.Action",
"name": "action",
"type": "uint8"
},
{
"internalType": "bool",
"name": "isFreezable",
"type": "bool"
},
{
"internalType": "bytes4[]",
"name": "selectors",
"type": "bytes4[]"
}
],
"internalType": "struct Diamond.FacetCut[]",
"name": "facetCuts",
"type": "tuple[]"
},
{
"internalType": "address",
"name": "initAddress",
"type": "address"
},
{
"internalType": "bytes",
"name": "initCalldata",
"type": "bytes"
}
],
"internalType": "struct Diamond.DiamondCutData",
"name": "_diamondCut",
"type": "tuple"
}
],
"name": "upgradeChainFromVersion",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}"#;
serde_json::from_str(abi).unwrap()
});
123 changes: 62 additions & 61 deletions core/lib/types/src/protocol_upgrade.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
use std::convert::{TryFrom, TryInto};

use serde::{Deserialize, Serialize};
use zksync_basic_types::protocol_version::{
L1VerifierConfig, ProtocolSemanticVersion, ProtocolVersionId, VerifierParams,
use zksync_basic_types::{
ethabi,
protocol_version::{
L1VerifierConfig, ProtocolSemanticVersion, ProtocolVersionId, VerifierParams,
},
};
use zksync_contracts::{
BaseSystemContractsHashes, ADMIN_EXECUTE_UPGRADE_FUNCTION,
ADMIN_UPGRADE_CHAIN_FROM_VERSION_FUNCTION,
};
use zksync_contracts::BaseSystemContractsHashes;
use zksync_utils::{h256_to_u256, u256_to_account_address};

use crate::{
Expand Down Expand Up @@ -95,30 +101,13 @@ fn get_transaction_param_type() -> ParamType {
])
}

impl TryFrom<Log> for ProtocolUpgrade {
type Error = crate::ethabi::Error;

fn try_from(event: Log) -> Result<Self, Self::Error> {
let facet_cut_param_type = ParamType::Tuple(vec![
ParamType::Address,
ParamType::Uint(8),
ParamType::Bool,
ParamType::Array(Box::new(ParamType::FixedBytes(4))),
]);
let diamond_cut_data_param_type = ParamType::Tuple(vec![
ParamType::Array(Box::new(facet_cut_param_type)),
ParamType::Address,
ParamType::Bytes,
]);
let mut decoded = decode(
&[diamond_cut_data_param_type, ParamType::FixedBytes(32)],
&event.data.0,
)?;

let init_calldata = match decoded.remove(0) {
Token::Tuple(tokens) => tokens[2].clone().into_bytes().unwrap(),
_ => unreachable!(),
};
impl ProtocolUpgrade {
fn try_from_decoded_tokens(
tokens: Vec<ethabi::Token>,
transaction_hash: H256,
transaction_block_number: u64,
) -> Result<Self, crate::ethabi::Error> {
let init_calldata = tokens[2].clone().into_bytes().unwrap();

let transaction_param_type: ParamType = get_transaction_param_type();
let verifier_params_type = ParamType::Tuple(vec![
Expand Down Expand Up @@ -155,15 +144,12 @@ impl TryFrom<Log> for ProtocolUpgrade {

let factory_deps = decoded.remove(0).into_array().unwrap();

let eth_hash = event
.transaction_hash
.expect("Event transaction hash is missing");
let eth_block = event
.block_number
.expect("Event block number is missing")
.as_u64();

let tx = ProtocolUpgradeTx::decode_tx(transaction, eth_hash, eth_block, factory_deps);
let tx = ProtocolUpgradeTx::decode_tx(
transaction,
transaction_hash,
transaction_block_number,
factory_deps,
);
let bootloader_code_hash = H256::from_slice(&decoded.remove(0).into_fixed_bytes().unwrap());
let default_account_code_hash =
H256::from_slice(&decoded.remove(0).into_fixed_bytes().unwrap());
Expand Down Expand Up @@ -350,32 +336,47 @@ impl TryFrom<Call> for ProtocolUpgrade {
type Error = crate::ethabi::Error;

fn try_from(call: Call) -> Result<Self, Self::Error> {
// Reuses `ProtocolUpgrade::try_from`.
// `ProtocolUpgrade::try_from` only uses 3 log fields: `data`, `block_number`, `transaction_hash`.
// Others can be filled with dummy values.
// We build data as `call.data` without first 4 bytes which are for selector
// and append it with `bytes32(0)` for compatibility with old event data.
let data = call
.data
.into_iter()
.skip(4)
.chain(encode(&[Token::FixedBytes(H256::zero().0.to_vec())]))
.collect::<Vec<u8>>()
.into();
let log = Log {
address: Default::default(),
topics: Default::default(),
let Call {
data,
block_hash: Default::default(),
block_number: Some(call.eth_block.into()),
transaction_hash: Some(call.eth_hash),
transaction_index: Default::default(),
log_index: Default::default(),
transaction_log_index: Default::default(),
log_type: Default::default(),
removed: Default::default(),
};
ProtocolUpgrade::try_from(log)
eth_hash,
eth_block,
..
} = call;

if data.len() < 4 {
return Err(crate::ethabi::Error::InvalidData);
}

let (signature, data) = data.split_at(4);

let diamond_cut_tokens =
if signature.to_vec() == ADMIN_EXECUTE_UPGRADE_FUNCTION.short_signature().to_vec() {
ADMIN_EXECUTE_UPGRADE_FUNCTION
.decode_input(data)?
.pop()
.unwrap()
.into_tuple()
.unwrap()
} else if signature.to_vec()
== ADMIN_UPGRADE_CHAIN_FROM_VERSION_FUNCTION
.short_signature()
.to_vec()
{
let mut data = ADMIN_UPGRADE_CHAIN_FROM_VERSION_FUNCTION.decode_input(data)?;

assert_eq!(
data.len(),
2,
"The second method is expected to accept exactly 2 arguments"
);

// The second item must be a tuple of diamond cut data
data.pop().unwrap().into_tuple().unwrap()
} else {
return Err(crate::ethabi::Error::InvalidData);
};

ProtocolUpgrade::try_from_decoded_tokens(diamond_cut_tokens, eth_hash, eth_block)
}
}

Expand Down
1 change: 0 additions & 1 deletion core/lib/zksync_core_leftovers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -914,7 +914,6 @@ pub async fn start_eth_watch(

let eth_watch = EthWatch::new(
diamond_proxy_addr,
state_transition_manager_addr,
&governance.0,
Box::new(eth_client),
pool,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::{
/// Listens to operation events coming from the governance contract and saves new protocol upgrade proposals to the database.
#[derive(Debug)]
pub struct GovernanceUpgradesEventProcessor {
// zkSync diamond proxy if pre-shared bridge; state transition manager if post shared bridge.
// zkSync diamond proxy
target_contract_address: Address,
/// Last protocol version seen. Used to skip events for already known upgrade proposals.
last_seen_protocol_version: ProtocolSemanticVersion,
Expand Down
3 changes: 1 addition & 2 deletions core/node/eth_watch/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ pub struct EthWatch {
impl EthWatch {
pub async fn new(
diamond_proxy_addr: Address,
state_transition_manager_address: Option<Address>,
governance_contract: &Contract,
mut client: Box<dyn EthClient>,
pool: ConnectionPool<Core>,
Expand All @@ -63,7 +62,7 @@ impl EthWatch {
let priority_ops_processor =
PriorityOpsEventProcessor::new(state.next_expected_priority_id)?;
let governance_upgrades_processor = GovernanceUpgradesEventProcessor::new(
state_transition_manager_address.unwrap_or(diamond_proxy_addr),
diamond_proxy_addr,
state.last_seen_protocol_version,
governance_contract,
);
Expand Down
2 changes: 0 additions & 2 deletions core/node/eth_watch/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,6 @@ async fn create_test_watcher(connection_pool: ConnectionPool<Core>) -> (EthWatch
let client = MockEthClient::new();
let watcher = EthWatch::new(
Address::default(),
None,
&governance_contract(),
Box::new(client.clone()),
connection_pool,
Expand Down Expand Up @@ -284,7 +283,6 @@ async fn test_normal_operation_governance_upgrades() {
let mut client = MockEthClient::new();
let mut watcher = EthWatch::new(
Address::default(),
None,
&governance_contract(),
Box::new(client.clone()),
connection_pool.clone(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,6 @@ impl WiringLayer for EthWatchLayer {

let client = context.get_resource::<EthInterfaceResource>().await?.0;

let state_transition_manager_address = self
.contracts_config
.ecosystem_contracts
.as_ref()
.map(|a| a.state_transition_proxy_addr);

let eth_client = EthHttpQueryClient::new(
client,
self.contracts_config.diamond_proxy_addr,
Expand All @@ -62,7 +56,6 @@ impl WiringLayer for EthWatchLayer {
main_pool,
client: eth_client,
governance_contract: governance_contract(),
state_transition_manager_address,
diamond_proxy_address: self.contracts_config.diamond_proxy_addr,
poll_interval: self.eth_watch_config.poll_interval(),
}));
Expand All @@ -76,7 +69,6 @@ struct EthWatchTask {
main_pool: ConnectionPool<Core>,
client: EthHttpQueryClient,
governance_contract: Contract,
state_transition_manager_address: Option<Address>,
diamond_proxy_address: Address,
poll_interval: Duration,
}
Expand All @@ -90,7 +82,6 @@ impl Task for EthWatchTask {
async fn run(self: Box<Self>, stop_receiver: StopReceiver) -> anyhow::Result<()> {
let eth_watch = EthWatch::new(
self.diamond_proxy_address,
self.state_transition_manager_address,
&self.governance_contract,
Box::new(self.client),
self.main_pool,
Expand Down
Loading
Loading