From de0b0efd69ba30785f955e04b8784615a08c9e51 Mon Sep 17 00:00:00 2001 From: pgherveou Date: Thu, 10 Oct 2024 11:31:01 +0200 Subject: [PATCH] rpc updates --- substrate/frame/revive/rpc/demo/demo.ts | 130 ++++++------------ substrate/frame/revive/rpc/demo/package.json | 1 - substrate/frame/revive/rpc/demo/tsconfig.json | 2 +- substrate/frame/revive/rpc/src/lib.rs | 44 ++++++ .../frame/revive/rpc/src/rpc_methods_gen.rs | 4 + .../frame/transaction-payment/src/lib.rs | 1 - 6 files changed, 88 insertions(+), 94 deletions(-) diff --git a/substrate/frame/revive/rpc/demo/demo.ts b/substrate/frame/revive/rpc/demo/demo.ts index c6a3f593c06f..ac0067ad9e16 100644 --- a/substrate/frame/revive/rpc/demo/demo.ts +++ b/substrate/frame/revive/rpc/demo/demo.ts @@ -1,96 +1,44 @@ - -import { Contract, ContractFactory, JsonRpcSigner, parseEther, encodeRlp, AddressLike, getBytes, JsonRpcProvider } from 'ethers'; +//! Run with bun run demo.ts +import { Contract, ContractFactory, encodeRlp, getBytes, JsonRpcProvider } from 'ethers'; const provider = new JsonRpcProvider('http://localhost:9090'); const signer = await provider.getSigner(); console.log(`Signer address: ${await signer.getAddress()}, Nonce: ${await signer.getNonce()}`); - -const code = getBytes('0x50564d0001010424009000022363616c6cdeadbeef63616c6c5f6e657665726465706c6f797365616c5f72657475726e041001000000007365616c5f72657475726e051b03000a63616c6c5f6e6576657204066465706c6f79060463616c6c062c06011f000406081b1c06100408130013000211fc03100408040001040904040706100a05004e13005129a4b800'); -const args = new Uint8Array() -const bytecode = encodeRlp([ code, args ]); - -const contractFactory = new ContractFactory([], bytecode, signer); -const contract = await contractFactory.deploy(); -await contract.waitForDeployment(); -const address = await contract.getAddress(); -console.log(`Contract deployed: ${address}`); - -//main().catch(console.error); - - - -// const nonce = await signer.getNonce(); -// console.log(`Nonce: ${nonce}`); -// -// document.getElementById('transferButton')?.addEventListener('click', async () => { -// const address = (document.getElementById('transferInput') as HTMLInputElement).value; -// await transfer(address); -// }); -// -// document.getElementById('deployButton')?.addEventListener('click', async () => { -// await deploy(); -// }); -// document.getElementById('deployAndCallButton')?.addEventListener('click', async () => { -// const nonce = await signer.getNonce(); -// console.log(`deploy with nonce: ${nonce}`); -// -// const address = await deploy(); -// if (address) { -// const nonce = await signer.getNonce(); -// console.log(`call with nonce: ${nonce}`); -// await call(address); -// } -// -// }); -// document.getElementById('callButton')?.addEventListener('click', async () => { -// const address = (document.getElementById('callInput') as HTMLInputElement).value; -// await call(address); -// }); -// -// async function deploy() { -// console.log('Deploying contract...'); -// -// const code = getBytes('0x50564d0001010424009000022363616c6cdeadbeef63616c6c5f6e657665726465706c6f797365616c5f72657475726e041001000000007365616c5f72657475726e051b03000a63616c6c5f6e6576657204066465706c6f79060463616c6c062c06011f000406081b1c06100408130013000211fc03100408040001040904040706100a05004e13005129a4b800'); -// const args = new Uint8Array() -// const bytecode = encodeRlp([ code, args ]); -// -// const contractFactory = new ContractFactory([], bytecode, signer); -// -// try { -// const contract = await contractFactory.deploy(); -// await contract.waitForDeployment(); -// const address = await contract.getAddress(); -// console.log(`Contract deployed: ${address}`); -// return address; -// } catch (e) { -// console.error('Failed to deploy contract', e); -// return; -// } -// } -// -// async function call(address: string) { -// const abi = ['function getValue() view returns (uint256)', 'function setValue(uint256 _value)']; -// -// const contract = new Contract(address, abi, signer); -// const tx = await contract.setValue(42); -// -// console.log('Transaction hash:', tx.hash); -// } -// -// async function transfer(to: AddressLike) { -// console.log(`transferring 1 DOT to ${to}...`); -// try { -// const tx = await signer.sendTransaction({ -// to, -// value: parseEther('1.0'), -// }); -// -// const receipt = await tx.wait(); -// console.log(`Transaction hash: ${receipt?.hash}`); -// } catch (e) { -// console.error('Failed to send transaction', e); -// return; -// } -// } -//}); +function str_to_bytes(str: string): Uint8Array { + return new TextEncoder().encode(str); +} +debugger +// deploy +async function deploy() { + console.log(`Deploying Contract...`); + const code = getBytes('0x50564d000101041c009000021c6465706c6f7963616c6c696e7075746465706f7369745f6576656e74041b02000000000d0000006465706f7369745f6576656e74696e707574050f0203066465706c6f79560463616c6c0681661b02810a0000030020002f003a00470055005600720081008c009a00a800a900af00ba00bd00c500d100e300eb00f100f300f800fc00040106014e1300021174ff03108800031584005217040980000405800004080610068e0003158000521702188000061008dc00011a800004078100297a1e04070000015219040806100cbd011088000115840002118c00130000021174ff03108800031584005217040980000405800004080610123b031580005217021880000610148a00011a800004078100297a1f0407000001521904080610186bff011088000115840002118c00130000040a102fa947287a12aa0308a70b070a0e527c1110c802cc012fbcfb14a909129cfc08cb0a2e0c1d128cff0004020000010102220101222c0c1103bc02bb042fabfb1299030f090a0513527a07090f089a091110a802aa012f9afb13004e0113008b88220a518488848a8868441451441122122a44449392b4244922882c492a5952fd00'); + + const args = str_to_bytes('ssh'); + const bytecode = encodeRlp([ code, new Uint8Array() ]); + console.log(`Bytecode length: ${bytecode.length}`, ); + const contractFactory = new ContractFactory([ + "constructor(bytes memory _data)", + ], bytecode, signer); + + console.log('Deploying contract with args:', args); + const contract = await contractFactory.deploy(args); + await contract.waitForDeployment(); + const address = await contract.getAddress(); + console.log(`Contract deployed: ${address}`); + return address; +} + +async function call(address: string) { + console.log(`Calling Contract at ${address}...`); + + const abi = ['function call(bytes data)']; + const contract = new Contract(address, abi, signer); + const tx = await contract.call(str_to_bytes('world')); + console.log('Call transaction hash:', tx.hash); +} + +const address = await deploy() +if (Deno.env.get('CALL') ) { + await call(address) +} diff --git a/substrate/frame/revive/rpc/demo/package.json b/substrate/frame/revive/rpc/demo/package.json index 0767ee797cff..0d45ada9d044 100644 --- a/substrate/frame/revive/rpc/demo/package.json +++ b/substrate/frame/revive/rpc/demo/package.json @@ -17,7 +17,6 @@ "devDependencies": { "@types/node": "^14.14.6", "prettier": "^3.3.3", - "ts-node": "^10.9.2", "typescript": "^4.1.2", "vite": "^2.5.0" } diff --git a/substrate/frame/revive/rpc/demo/tsconfig.json b/substrate/frame/revive/rpc/demo/tsconfig.json index 4fe7012decd8..9ca92c02de5f 100644 --- a/substrate/frame/revive/rpc/demo/tsconfig.json +++ b/substrate/frame/revive/rpc/demo/tsconfig.json @@ -1,5 +1,5 @@ { - "compilerOptions": { +"compilerOptions": { "target": "esnext", "module": "esnext", "moduleResolution": "node", diff --git a/substrate/frame/revive/rpc/src/lib.rs b/substrate/frame/revive/rpc/src/lib.rs index a472cca79656..6f750087b048 100644 --- a/substrate/frame/revive/rpc/src/lib.rs +++ b/substrate/frame/revive/rpc/src/lib.rs @@ -67,6 +67,12 @@ pub enum EthRpcError { /// The account was not found at the given address #[error("Account not found for address {0:?}")] AccountNotFound(H160), + /// Received an invalid transaction + #[error("Invalid transaction")] + InvalidTransaction, + /// Received an invalid transaction + #[error("Invalid transaction {0:?}")] + TransactionTypeNotSupported(Byte), } impl From for ErrorObjectOwned { @@ -147,6 +153,44 @@ impl EthRpcServer for EthRpcServerImpl { Ok(hash) } + async fn send_transaction(&self, transaction: GenericTransaction) -> RpcResult { + log::debug!(target: LOG_TARGET, "{transaction:#?}"); + let GenericTransaction { from, gas, gas_price, input, to, value, r#type, .. } = transaction; + + let Some(from) = from else { + log::debug!(target: LOG_TARGET, "Transaction must have a sender"); + return Err(EthRpcError::InvalidTransaction.into()); + }; + + let account = self + .accounts + .iter() + .find(|account| account.address() == from) + .ok_or(EthRpcError::AccountNotFound(from))?; + + let gas_price = gas_price.unwrap_or_else(|| U256::from(GAS_PRICE)); + let chain_id = Some(self.client.chain_id().into()); + let input = input.unwrap_or_default(); + let value = value.unwrap_or_default(); + let r#type = r#type.unwrap_or_default(); + + let Some(gas) = gas else { + log::debug!(target: LOG_TARGET, "Transaction must have a gas limit"); + return Err(EthRpcError::InvalidTransaction.into()); + }; + + let r#type = Type0::try_from_byte(r#type.clone()) + .map_err(|_| EthRpcError::TransactionTypeNotSupported(r#type))?; + + let nonce = self.get_transaction_count(from, BlockTag::Latest.into()).await?; + + let tx = + TransactionLegacyUnsigned { chain_id, gas, gas_price, input, nonce, to, value, r#type }; + let tx = account.sign_transaction(tx); + let rlp_bytes = rlp::encode(&tx).to_vec(); + self.send_raw_transaction(Bytes(rlp_bytes)).await + } + async fn get_block_by_hash( &self, block_hash: H256, diff --git a/substrate/frame/revive/rpc/src/rpc_methods_gen.rs b/substrate/frame/revive/rpc/src/rpc_methods_gen.rs index eb6bebe232b4..23e962e6ca43 100644 --- a/substrate/frame/revive/rpc/src/rpc_methods_gen.rs +++ b/substrate/frame/revive/rpc/src/rpc_methods_gen.rs @@ -146,6 +146,10 @@ pub trait EthRpc { #[method(name = "eth_sendRawTransaction")] async fn send_raw_transaction(&self, transaction: Bytes) -> RpcResult; + /// Signs and submits a transaction. + #[method(name = "eth_sendTransaction")] + async fn send_transaction(&self, transaction: GenericTransaction) -> RpcResult; + /// The string value of current network id #[method(name = "net_version")] async fn net_version(&self) -> RpcResult; diff --git a/substrate/frame/transaction-payment/src/lib.rs b/substrate/frame/transaction-payment/src/lib.rs index 7e524f1d606f..c17ab393b5d3 100644 --- a/substrate/frame/transaction-payment/src/lib.rs +++ b/substrate/frame/transaction-payment/src/lib.rs @@ -577,7 +577,6 @@ impl Pallet { where T::RuntimeCall: Dispatchable, { - log::info!(target: "evm", "compute_fee: len: {len:?}, info: {info:?}, tip: {tip:?}"); Self::compute_fee_details(len, info, tip).final_fee() }