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

3rd party ethereum node integration adjustments #3153

Merged
merged 3 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
1 change: 1 addition & 0 deletions tee-worker/omni-executor/Cargo.lock

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

6 changes: 6 additions & 0 deletions tee-worker/omni-executor/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,10 @@ RUN cargo build --release

FROM ubuntu:22.04
COPY --from=builder /usr/src/omni-executor/target/release/executor-worker /usr/local/bin/executor-worker

RUN \
apt-get update && \
apt-get install -y ca-certificates && \
apt-get clean

CMD ["executor-worker"]
3 changes: 3 additions & 0 deletions tee-worker/omni-executor/ethereum/intent-executor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,8 @@ async-trait = { workspace = true }
executor-core = { path = "../../executor-core" }
log = { workspace = true }

[dev-dependencies]
tokio = { workspace = true }

[lints]
workspace = true
86 changes: 78 additions & 8 deletions tee-worker/omni-executor/ethereum/intent-executor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

use std::str::FromStr;

use alloy::network::EthereumWallet;
use alloy::network::{EthereumWallet, TransactionBuilder};
use alloy::primitives::{Address, U256};
use alloy::providers::{Provider, ProviderBuilder, WalletProvider};
use alloy::rpc::types::{TransactionInput, TransactionRequest};
Expand All @@ -43,22 +43,28 @@ impl IntentExecutor for EthereumIntentExecutor {
info!("Executin intent: {:?}", intent);
// todo: this should be retrieved from key_store
let signer = PrivateKeySigner::from_str(
"0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d",
"0x59c6995e998f97a5a0044964f0945389dc9e86dae86c7a8412f4603b6b78690d",
)
.unwrap();
let wallet = EthereumWallet::from(signer);
let provider = ProviderBuilder::new()
.with_recommended_fillers()
.wallet(wallet)
.on_http(self.rpc_url.parse().map_err(|e| error!("Could not parse rpc url: {:?}", e))?);
let account =
provider.get_account(provider.signer_addresses().next().unwrap()).await.unwrap();
let nonce = provider
.get_transaction_count(provider.signer_addresses().next().unwrap())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dumb question: what's the diff?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eth_getAccount is not listend in ethereum api documentation https://ethereum.github.io/execution-apis/api-documentation/ , it worked for locally run anvil node but failed while I was testing the integration with infura's api.

.await
.unwrap();
let gas_price = provider.get_gas_price().await.unwrap();

match intent {
Intent::TransferEthereum(to, value) => {
let tx = TransactionRequest::default()
let mut tx = TransactionRequest::default()
.to(Address::from(to))
.nonce(account.nonce)
.nonce(nonce)
.value(U256::from_be_bytes(value));

tx.set_gas_price(gas_price);
let pending_tx = provider.send_transaction(tx).await.map_err(|e| {
error!("Could not send transaction: {:?}", e);
})?;
Expand All @@ -68,10 +74,12 @@ impl IntentExecutor for EthereumIntentExecutor {
})?;
},
Intent::CallEthereum(address, input) => {
let tx = TransactionRequest::default()
let mut tx = TransactionRequest::default()
.to(Address::from(address))
.nonce(account.nonce)
.nonce(nonce)
.input(TransactionInput::from(input));

tx.set_gas_price(gas_price);
let pending_tx = provider.send_transaction(tx).await.map_err(|e| {
error!("Could not send transaction: {:?}", e);
})?;
Expand All @@ -84,3 +92,65 @@ impl IntentExecutor for EthereumIntentExecutor {
Ok(())
}
}

#[cfg(test)]
pub mod test {
use alloy::hex;
use alloy::hex::FromHex;
use alloy::network::{EthereumWallet, NetworkWallet, TransactionBuilder};
use alloy::primitives::Address;
use alloy::providers::{Provider, ProviderBuilder, WalletProvider};
use alloy::rpc::types::{TransactionInput, TransactionRequest};
use alloy::signers::local::PrivateKeySigner;
use log::error;
use std::str::FromStr;

// #[tokio::test]
pub async fn test() {
// place url here:
let url = "";

let signer = PrivateKeySigner::from_str(
"0x59c6995e998f97a5a0044964f0945389dc9e86dae86c7a8412f4603b6b78690d",
)
.unwrap();
let wallet = EthereumWallet::from(signer);

let provider = ProviderBuilder::new()
.with_recommended_fillers()
.wallet(wallet)
.on_http(url.parse().map_err(|e| error!("Could not parse rpc url: {:?}", e)).unwrap());
let nonce = provider
.get_transaction_count(provider.signer_addresses().next().unwrap())
.await
.unwrap();
let gas_price = provider.get_gas_price().await.unwrap();

let mut tx = TransactionRequest::default()
.to(Address::from_hex("0x1f754692f0b0578d6af97faed6319542c9ffd468").unwrap())
.nonce(nonce)
.input(TransactionInput::from(hex::decode("0x2166e8280000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001e4c6974656e747279204f6d6e694163636f756e7420657865637574696f6e0000").unwrap()));

tx.set_gas_price(gas_price);

let pending_tx = provider
.send_transaction(tx)
.await
.map_err(|e| {
std::println!("Could not send transaction: {:?}", e);
})
.map_err(|e| {
std::println!("Could not get transaction receipt: {:?}", e);
()
})
.unwrap();

pending_tx
.get_receipt()
.await
.map_err(|e| {
error!("Could not get transaction receipt: {:?}", e);
})
.unwrap();
}
}
Binary file not shown.
180 changes: 92 additions & 88 deletions tee-worker/omni-executor/parentchain/listener/src/event_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,106 +154,110 @@ impl<
Error::NonRecoverableError
})?;

let intent = match decoded.intent {
let maybe_intent = match decoded.intent {
crate::litentry_rococo::runtime_types::core_primitives::intent::Intent::CallEthereum(call_ethereum) => {
Intent::CallEthereum(call_ethereum.address.to_fixed_bytes(), call_ethereum.input.0)
Some(Intent::CallEthereum(call_ethereum.address.to_fixed_bytes(), call_ethereum.input.0))
},
crate::litentry_rococo::runtime_types::core_primitives::intent::Intent::TransferEthereum(transfer) => {
Intent::TransferEthereum(transfer.to.to_fixed_bytes(), transfer.value)
}
Some(Intent::TransferEthereum(transfer.to.to_fixed_bytes(), transfer.value))
},
crate::litentry_rococo::runtime_types::core_primitives::intent::Intent::SystemRemark(_) => None,
crate::litentry_rococo::runtime_types::core_primitives::intent::Intent::TransferNative(_) => None,
};

//to explicitly handle all intent variants
match intent {
Intent::CallEthereum(_, _) => {
self.ethereum_intent_executor.execute(intent).await.map_err(|_| {
// assume for now we can easily recover
log::error!("Error executing intent");
Error::RecoverableError
})?;
},
Intent::TransferEthereum(_, _) => {
self.ethereum_intent_executor.execute(intent).await.map_err(|_| {
// assume for now we can easily recover
log::error!("Error executing intent");
Error::RecoverableError
})?;
},
}
if let Some(intent) = maybe_intent {
// to explicitly handle all intent variants
match intent {
Intent::CallEthereum(_, _) => {
self.ethereum_intent_executor.execute(intent).await.map_err(|_| {
// assume for now we can easily recover
log::error!("Error executing intent");
Error::RecoverableError
})?;
},
Intent::TransferEthereum(_, _) => {
self.ethereum_intent_executor.execute(intent).await.map_err(|_| {
// assume for now we can easily recover
log::error!("Error executing intent");
Error::RecoverableError
})?;
},
}

log::debug!("Intent executed, publishing result");
log::debug!("Intent executed, publishing result");

// todo: the whole signing part should be encapsulated in separate component like `TransactionSigner`
//we need to report back to parachain intent result
let decoded =
crate::litentry_rococo::omni_account::events::IntentRequested::decode_as_fields(
&mut event.field_bytes.as_slice(),
&mut fields,
metadata.types(),
)
.map_err(|_| {
log::error!("Could not decode event {:?}", event.id);
Error::NonRecoverableError
})?;
// todo: the whole signing part should be encapsulated in separate component like `TransactionSigner`
//we need to report back to parachain intent result
let decoded =
crate::litentry_rococo::omni_account::events::IntentRequested::decode_as_fields(
&mut event.field_bytes.as_slice(),
&mut fields,
metadata.types(),
)
.map_err(|_| {
log::error!("Could not decode event {:?}", event.id);
Error::NonRecoverableError
})?;

let execution_result =
crate::litentry_rococo::omni_account::calls::types::intent_executed::Result::Success;
let execution_result =
crate::litentry_rococo::omni_account::calls::types::intent_executed::Result::Success;

let call = crate::litentry_rococo::tx().omni_account().intent_executed(
decoded.who,
decoded.intent,
execution_result,
);
let call = crate::litentry_rococo::tx().omni_account().intent_executed(
decoded.who,
decoded.intent,
execution_result,
);

let secret_key_bytes = self
.key_store
.read()
.map_err(|e| {
error!("Could not unseal key: {:?}", e);
})
.unwrap();
let signer = subxt_signer::sr25519::Keypair::from_secret_key(secret_key_bytes)
.map_err(|e| {
error!("Could not create secret key: {:?}", e);
})
.unwrap();
let secret_key_bytes = self
.key_store
.read()
.map_err(|e| {
error!("Could not unseal key: {:?}", e);
})
.unwrap();
let signer = subxt_signer::sr25519::Keypair::from_secret_key(secret_key_bytes)
.map_err(|e| {
error!("Could not create secret key: {:?}", e);
})
.unwrap();

let mut client = self.rpc_client_factory.new_client().await.map_err(|e| {
error!("Could not create RPC client: {:?}", e);
RecoverableError
})?;
let runtime_version = client.runtime_version().await.map_err(|e| {
error!("Could not get runtime version: {:?}", e);
RecoverableError
})?;
let genesis_hash = client.get_genesis_hash().await.map_err(|e| {
error!("Could not get genesis hash: {:?}", e);
RecoverableError
})?;
let nonce = *self.nonce.read().map_err(|e| {
error!("Could not read nonce: {:?}", e);
RecoverableError
})?;
let params = DefaultExtrinsicParamsBuilder::<ChainConfig>::new().nonce(nonce).build();
*self.nonce.write().map_err(|e| {
error!("Could not write nonce: {:?}", e);
RecoverableError
})? = nonce + 1;
let mut client = self.rpc_client_factory.new_client().await.map_err(|e| {
error!("Could not create RPC client: {:?}", e);
RecoverableError
})?;
let runtime_version = client.runtime_version().await.map_err(|e| {
error!("Could not get runtime version: {:?}", e);
RecoverableError
})?;
let genesis_hash = client.get_genesis_hash().await.map_err(|e| {
error!("Could not get genesis hash: {:?}", e);
RecoverableError
})?;
let nonce = *self.nonce.read().map_err(|e| {
error!("Could not read nonce: {:?}", e);
RecoverableError
})?;
let params = DefaultExtrinsicParamsBuilder::<ChainConfig>::new().nonce(nonce).build();
*self.nonce.write().map_err(|e| {
error!("Could not write nonce: {:?}", e);
RecoverableError
})? = nonce + 1;

let state = tx::ClientState::<ChainConfig> {
metadata: { metadata },
genesis_hash: ChainConfig::Hash::decode(&mut genesis_hash.as_slice()).unwrap(),
runtime_version: tx::RuntimeVersion {
spec_version: runtime_version.spec_version,
transaction_version: runtime_version.transaction_version,
},
};
let signed_call = tx::create_signed(&call, &state, &signer, params).unwrap();
client.submit_tx(signed_call.encoded()).await.map_err(|e| {
error!("Error while submitting tx: {:?}", e);
RecoverableError
})?;
log::debug!("Result published");
let state = tx::ClientState::<ChainConfig> {
metadata: { metadata },
genesis_hash: ChainConfig::Hash::decode(&mut genesis_hash.as_slice()).unwrap(),
runtime_version: tx::RuntimeVersion {
spec_version: runtime_version.spec_version,
transaction_version: runtime_version.transaction_version,
},
};
let signed_call = tx::create_signed(&call, &state, &signer, params).unwrap();
client.submit_tx(signed_call.encoded()).await.map_err(|e| {
error!("Error while submitting tx: {:?}", e);
RecoverableError
})?;
log::debug!("Result published");
}
Ok(())
}
}