From 98e36345767898b4a7714531418acb4ed9908a59 Mon Sep 17 00:00:00 2001 From: harry Date: Tue, 13 Dec 2022 23:12:01 +0800 Subject: [PATCH 01/10] eip1559 support fix make lint Eip1559 (#780) * merge evm runners * remove legacy action * use new FeeCalcultor * fix test evm_tx_hash * fix gas_price Co-authored-by: simonjiao fix lint --- src/components/config/src/abci/mod.rs | 3 + .../contracts/baseapp/src/extensions.rs | 10 +- src/components/contracts/baseapp/src/lib.rs | 36 +- .../contracts/modules/account/src/impls.rs | 10 + .../contracts/modules/account/src/lib.rs | 4 +- .../contracts/modules/ethereum/src/impls.rs | 110 +++- .../contracts/modules/ethereum/src/lib.rs | 81 ++- .../contracts/modules/evm/Cargo.toml | 1 + .../modules/evm/precompile/utils/Cargo.toml | 1 + .../contracts/modules/evm/src/impls.rs | 7 + .../contracts/modules/evm/src/lib.rs | 12 +- .../modules/evm/src/runtime/runner.rs | 93 ++- .../modules/evm/tests/evm_integration.rs | 2 + .../template/tests/template_integration.rs | 6 +- .../contracts/primitives/evm/src/lib.rs | 4 +- .../contracts/primitives/mocks/src/lib.rs | 6 +- .../contracts/primitives/rpc-core/Cargo.toml | 2 + .../primitives/rpc-core/src/types/block.rs | 2 + .../rpc-core/src/types/call_request.rs | 4 + .../primitives/rpc-core/src/types/mod.rs | 2 +- .../primitives/rpc-core/src/types/receipt.rs | 3 + .../rpc-core/src/types/transaction.rs | 68 ++- .../rpc-core/src/types/transaction_request.rs | 62 +- .../primitives/traits/src/account.rs | 11 +- .../contracts/primitives/traits/src/base.rs | 2 +- .../contracts/primitives/traits/src/evm.rs | 3 + .../primitives/types/src/actions/ethereum.rs | 2 +- .../primitives/types/src/actions/evm.rs | 6 + .../primitives/types/src/assemble.rs | 2 +- .../contracts/primitives/utils/Cargo.toml | 2 + .../contracts/primitives/wasm/Cargo.toml | 2 +- .../contracts/primitives/wasm/src/wasm.rs | 47 +- src/components/contracts/rpc/src/eth.rs | 573 +++++++++++++----- .../contracts/rpc/src/eth_filter.rs | 2 +- .../contracts/rpc/src/eth_pubsub.rs | 2 +- src/components/finutils/Cargo.toml | 2 +- .../finutils/src/txn_builder/mod.rs | 1 - src/components/wallet_mobile/Cargo.toml | 2 +- src/components/wasm/Cargo.toml | 4 +- src/libs/bitmap/src/lib.rs | 2 +- src/libs/credentials/Cargo.toml | 2 +- 41 files changed, 906 insertions(+), 290 deletions(-) diff --git a/src/components/config/src/abci/mod.rs b/src/components/config/src/abci/mod.rs index b97a41c6b..f20193426 100644 --- a/src/components/config/src/abci/mod.rs +++ b/src/components/config/src/abci/mod.rs @@ -88,6 +88,7 @@ pub struct CheckPointConfig { // Fix the amount in the delegators that staking did not modify when it punished the validator. pub fix_delegators_am_height: u64, pub validators_limit_v2_height: u64, + pub enable_eip1559_height: u64, } impl CheckPointConfig { @@ -127,6 +128,7 @@ impl CheckPointConfig { proper_gas_set_height: 0, fix_delegators_am_height: 0, validators_limit_v2_height: 0, + enable_eip1559_height: 0, }; #[cfg(not(feature = "debug_env"))] let config = CheckPointConfig { @@ -156,6 +158,7 @@ impl CheckPointConfig { fix_undelegation_missing_reward_height: 3000000, fix_delegators_am_height: 30000000, validators_limit_v2_height: 30000000, + enable_eip1559_height: 40000000, }; let content = toml::to_string(&config).unwrap(); file.write_all(content.as_bytes()).unwrap(); diff --git a/src/components/contracts/baseapp/src/extensions.rs b/src/components/contracts/baseapp/src/extensions.rs index d17977e40..e75a9eaf9 100644 --- a/src/components/contracts/baseapp/src/extensions.rs +++ b/src/components/contracts/baseapp/src/extensions.rs @@ -4,7 +4,7 @@ use fp_core::{ context::Context, transaction::{ActionResult, SignedExtension}, }; -use fp_traits::account::{AccountAsset, FeeCalculator}; +use fp_traits::{account::AccountAsset, evm::FeeCalculator}; use fp_types::crypto::Address; use primitive_types::U256; use ruc::*; @@ -64,7 +64,9 @@ impl SignedExtension for CheckFee { type Pre = (Address, U256); fn validate(&self, ctx: &Context, who: &Self::AccountId) -> Result<()> { - let min_fee = ::FeeCalculator::min_fee(); + let min_fee = ::FeeCalculator::min_gas_price( + ctx.header.height as u64, + ); let tx_fee = match self.0 { None => min_fee, Some(fee) => { @@ -85,7 +87,9 @@ impl SignedExtension for CheckFee { } fn pre_execute(self, ctx: &Context, who: &Self::AccountId) -> Result { - let min_fee = ::FeeCalculator::min_fee(); + let min_fee = ::FeeCalculator::min_gas_price( + ctx.header.height as u64, + ); let tx_fee = match self.0 { None => min_fee, Some(fee) => { diff --git a/src/components/contracts/baseapp/src/lib.rs b/src/components/contracts/baseapp/src/lib.rs index 02de696a1..1f902f0b5 100644 --- a/src/components/contracts/baseapp/src/lib.rs +++ b/src/components/contracts/baseapp/src/lib.rs @@ -13,7 +13,7 @@ pub mod tm_events; use crate::modules::ModuleManager; use abci::Header; -use ethereum::BlockV0 as Block; +use ethereum::BlockV2 as Block; use evm_precompile::{self, FindoraPrecompiles}; use fin_db::{FinDB, RocksDB}; use fp_core::context::Context as Context2; @@ -25,9 +25,11 @@ use fp_core::{ }; use fp_evm::BlockId; use fp_traits::{ - account::{AccountAsset, FeeCalculator}, + account::AccountAsset, base::BaseProvider, - evm::{DecimalsMapping, EthereumAddressMapping, EthereumDecimalsMapping}, + evm::{ + DecimalsMapping, EthereumAddressMapping, EthereumDecimalsMapping, + }, }; use fp_types::{actions::xhub::NonConfidentialOutput, actions::Action, crypto::Address}; use lazy_static::lazy_static; @@ -54,6 +56,23 @@ const CHAIN_STATE_PATH: &str = "state.db"; const CHAIN_HISTORY_DATA_PATH: &str = "history.db"; const BLOCKS_IN_DAY: u64 = 4 * 60 * 24; +const INITIAL_BASE_FEE: u64 = 1000000000; +const ELASTICITY_MULTIPLIER: u64 = 2; +const BASE_FEE_MAX_CHANGE_DENOMINATOR: u64 = 8; + +#[inline(always)] +pub fn get_initial_base_fee() -> U256 { + U256::from(INITIAL_BASE_FEE) +} +#[inline(always)] +pub fn get_elasticity_multiplier() -> U256 { + U256::from(ELASTICITY_MULTIPLIER) +} +#[inline(always)] +pub fn get_base_fee_max_change_denominator() -> U256 { + U256::from(BASE_FEE_MAX_CHANGE_DENOMINATOR) +} + #[derive(Clone)] pub struct BaseApp { /// application name from abci.Info @@ -81,17 +100,8 @@ pub struct BaseApp { impl module_template::Config for BaseApp {} -pub struct StableTxFee; - -impl FeeCalculator for StableTxFee { - fn min_fee() -> U256 { - // TX_FEE_MIN - U256::from(1_0000_0000_0000_0000_u64) - } -} - impl module_account::Config for BaseApp { - type FeeCalculator = StableTxFee; + type FeeCalculator = (); } parameter_types! { diff --git a/src/components/contracts/modules/account/src/impls.rs b/src/components/contracts/modules/account/src/impls.rs index c0ff983cf..e3cbba4af 100644 --- a/src/components/contracts/modules/account/src/impls.rs +++ b/src/components/contracts/modules/account/src/impls.rs @@ -242,4 +242,14 @@ impl AccountAsset
for App { ) -> Result<()> { Allowances::insert(ctx.state.write().borrow_mut(), owner, spender, &amount) } + + fn income(ctx: &Context, who: &Address, value: U256) -> Result<()> { + if value.is_zero() { + return Ok(()); + } + + let mut sa = Self::account_of(ctx, who, None).c(d!("account does not exist"))?; + sa.balance = sa.balance.checked_add(value).c(d!("balance overflow"))?; + AccountStore::insert(ctx.state.write().borrow_mut(), who, &sa) + } } diff --git a/src/components/contracts/modules/account/src/lib.rs b/src/components/contracts/modules/account/src/lib.rs index 7429c47dc..4192005c6 100644 --- a/src/components/contracts/modules/account/src/lib.rs +++ b/src/components/contracts/modules/account/src/lib.rs @@ -12,8 +12,8 @@ mod tests; use abci::{RequestQuery, ResponseQuery}; use fp_core::{context::Context, module::AppModule}; use fp_traits::{ - account::{AccountAsset, FeeCalculator}, - evm::{DecimalsMapping, EthereumDecimalsMapping}, + account::AccountAsset, + evm::{DecimalsMapping, EthereumDecimalsMapping, FeeCalculator}, }; use fp_types::crypto::Address; use std::marker::PhantomData; diff --git a/src/components/contracts/modules/ethereum/src/impls.rs b/src/components/contracts/modules/ethereum/src/impls.rs index 61654416b..5346e5193 100644 --- a/src/components/contracts/modules/ethereum/src/impls.rs +++ b/src/components/contracts/modules/ethereum/src/impls.rs @@ -1,10 +1,7 @@ use crate::storage::*; use crate::{App, Config, ContractLog, TransactionExecuted}; use config::abci::global_cfg::CFG; -use ethereum::{ - BlockV0 as Block, LegacyTransactionMessage, ReceiptV0 as Receipt, - TransactionV0 as Transaction, -}; +use ethereum::{BlockV2 as Block, ReceiptV0 as Receipt, TransactionV2 as Transaction}; use ethereum_types::{Bloom, BloomInput, H160, H256, H64, U256}; use evm::{ExitFatal, ExitReason}; use fp_core::{ @@ -16,10 +13,8 @@ use fp_core::{ use fp_events::Event; use fp_evm::{BlockId, CallOrCreateInfo, Runner, TransactionStatus}; use fp_storage::{Borrow, BorrowMut}; -use fp_types::{ - actions::evm as EvmAction, - crypto::{secp256k1_ecdsa_recover, HA256}, -}; +// use fp_types::crypto::secp256k1_ecdsa_recover; +use fp_types::{actions::evm as EvmAction, crypto::HA256}; use fp_utils::{proposer_converter, timestamp_converter}; use ruc::*; use sha3::{Digest, Keccak256}; @@ -63,14 +58,28 @@ impl App { pub fn recover_signer(transaction: &Transaction) -> Option { let mut sig = [0u8; 65]; let mut msg = [0u8; 32]; - sig[0..32].copy_from_slice(&transaction.signature.r()[..]); - sig[32..64].copy_from_slice(&transaction.signature.s()[..]); - sig[64] = transaction.signature.standard_v(); - msg.copy_from_slice( - &LegacyTransactionMessage::from(transaction.clone()).hash()[..], - ); - - let pubkey = secp256k1_ecdsa_recover(&sig, &msg).ok()?; + match transaction { + Transaction::Legacy(t) => { + sig[0..32].copy_from_slice(&t.signature.r()[..]); + sig[32..64].copy_from_slice(&t.signature.s()[..]); + sig[64] = t.signature.standard_v(); + msg.copy_from_slice( + ðereum::LegacyTransactionMessage::from(t.clone()).hash()[..], + ); + } + Transaction::EIP1559(t) => { + sig[0..32].copy_from_slice(&t.r[..]); + sig[32..64].copy_from_slice(&t.s[..]); + sig[64] = t.odd_y_parity as u8; + msg.copy_from_slice( + ðereum::EIP1559TransactionMessage::from(t.clone()).hash()[..], + ); + } + _ => { + return None; + } + } + let pubkey = fp_types::crypto::secp256k1_ecdsa_recover(&sig, &msg).ok()?; Some(H160::from(H256::from_slice( Keccak256::digest(pubkey).as_slice(), ))) @@ -225,8 +234,7 @@ impl App { let source = Self::recover_signer_fast(ctx, &transaction) .ok_or_else(|| eg!("ExecuteTransaction: InvalidSignature"))?; - let transaction_hash = - H256::from_slice(Keccak256::digest(&rlp::encode(&transaction)).as_slice()); + let transaction_hash = transaction.hash(); let transaction_index = if just_check { 0 @@ -236,22 +244,66 @@ impl App { txns.len() as u32 }; - let gas_limit = transaction.gas_limit; + let ( + nonce, + gas_price, + gas_limit, + action, + value, + input, + _max_priority_fee_per_gas, + _max_fee_per_gas, + _chain_id, + _access_list, + ) = match &transaction { + Transaction::Legacy(transaction) => ( + transaction.nonce, + transaction.gas_price, + transaction.gas_limit, + transaction.action, + transaction.value, + transaction.input.clone(), + transaction.gas_price, + U256::from(0), + match transaction.signature.chain_id() { + Some(chain_id) => chain_id, + None => return Err(eg!("Must provide chainId")), + }, + vec![], + ), + Transaction::EIP1559(transaction) => ( + transaction.nonce, + transaction.max_fee_per_gas, + transaction.gas_limit, + transaction.action, + transaction.value, + transaction.input.clone(), + transaction.max_fee_per_gas, + transaction.max_priority_fee_per_gas, + transaction.chain_id, + transaction.access_list.clone(), + ), + _ => { + return Err(eg!("Unsupported Transaction Type")); + } + }; let execute_ret = Self::execute_transaction( ctx, source, - transaction.input.clone(), - transaction.value, - transaction.gas_limit, - Some(transaction.gas_price), - Some(transaction.nonce), - transaction.action, + input, + value, + gas_limit, + Some(gas_price), + None, + None, + Some(nonce), + action, ); if let Err(e) = execute_ret { let mut to = Default::default(); - if let ethereum::TransactionAction::Call(target) = transaction.action { + if let ethereum::TransactionAction::Call(target) = action { to = target; } events.push(Event::emit_event( @@ -410,6 +462,8 @@ impl App { value: U256, gas_limit: U256, gas_price: Option, + max_fee_per_gas: Option, + max_priority_fee_per_gas: Option, nonce: Option, action: ethereum::TransactionAction, ) -> Result<(Option, Option, CallOrCreateInfo)> { @@ -424,6 +478,8 @@ impl App { value, gas_limit: gas_limit.low_u64(), gas_price, + max_fee_per_gas, + max_priority_fee_per_gas, nonce, }, C::config(), @@ -440,6 +496,8 @@ impl App { value, gas_limit: gas_limit.low_u64(), gas_price, + max_fee_per_gas, + max_priority_fee_per_gas, nonce, }, C::config(), diff --git a/src/components/contracts/modules/ethereum/src/lib.rs b/src/components/contracts/modules/ethereum/src/lib.rs index 07c180354..de1c16f69 100644 --- a/src/components/contracts/modules/ethereum/src/lib.rs +++ b/src/components/contracts/modules/ethereum/src/lib.rs @@ -5,6 +5,7 @@ mod basic; mod impls; use config::abci::global_cfg::CFG; +use ethereum::TransactionV2 as Transaction; use ethereum_types::{H160, H256, U256}; use evm::Config as EvmConfig; use fp_core::context::RunTxMode; @@ -54,7 +55,7 @@ pub trait Config { pub mod storage { use ethereum::{ - BlockV0 as Block, ReceiptV0 as Receipt, TransactionV0 as Transaction, + BlockV2 as Block, ReceiptV0 as Receipt, TransactionV2 as Transaction, }; use ethereum_types::U256; use fp_evm::TransactionStatus; @@ -176,60 +177,92 @@ impl ValidateUnsigned for App { fn validate_unsigned(ctx: &Context, call: &Self::Call) -> Result<()> { let Action::Transact(transaction) = call; - if let Some(chain_id) = transaction.signature.chain_id() { - if chain_id != C::ChainId::get() { - return Err(eg!(format!( - "InvalidChainId, got {}, but expected {}", - chain_id, - C::ChainId::get() - ))); + + let ( + nonce, + gas_price, + gas_limit, + value, + chain_id, + _max_fee_per_gas, + _max_priority_fee_per_gas, + _is_eip1559, + ) = match transaction { + Transaction::Legacy(t) => ( + t.nonce, + t.gas_price, + t.gas_limit, + t.value, + match t.signature.chain_id() { + Some(chain_id) => chain_id, + None => return Err(eg!("Must provide chainId")), + }, + U256::zero(), + U256::zero(), + false, + ), + Transaction::EIP1559(t) => ( + t.nonce, + U256::zero(), + t.gas_limit, + t.value, + t.chain_id, + t.max_fee_per_gas, + t.max_priority_fee_per_gas, + true, + ), + _ => { + return Err(eg!("Transaction Type Error")); } - } else { - return Err(eg!("Must provide chainId".to_string())); + }; + + if chain_id != C::ChainId::get() { + return Err(eg!(format!( + "InvalidChainId, got {}, but expected {}", + chain_id, + C::ChainId::get() + ))); } let origin = Self::recover_signer_fast(ctx, transaction) .ok_or_else(|| eg!("ExecuteTransaction: InvalidSignature"))?; // Same as go ethereum, Min gas limit is 21000. - if transaction.gas_limit < U256::from(21000) - || transaction.gas_limit > C::BlockGasLimit::get() - { + if gas_limit < U256::from(21000) || gas_limit > C::BlockGasLimit::get() { return Err(eg!(format!( "InvalidGasLimit: got {}, the gas limit must be in range [21000, {}]", - transaction.gas_limit, + gas_limit, C::BlockGasLimit::get() ))); } let min_gas_price = C::FeeCalculator::min_gas_price(ctx.header.height as u64); - if transaction.gas_price < min_gas_price { + if gas_price < min_gas_price { return Err(eg!(format!( "InvalidGasPrice: got {}, but the minimum gas price is {}", - transaction.gas_price, min_gas_price + gas_price, min_gas_price ))); } let account_id = C::AddressMapping::convert_to_account_id(origin); let account = C::AccountAsset::account_of(ctx, &account_id, None).unwrap_or_default(); - let nonce = account.nonce; - let balance = account.balance; - if transaction.nonce < nonce { + if nonce < account.nonce { return Err(eg!(format!( "InvalidNonce: origin: {:?}, got {}, but expected {}", - origin, transaction.nonce, nonce + origin, nonce, account.nonce ))); } - let fee = transaction.gas_price.saturating_mul(transaction.gas_limit); - let total_payment = transaction.value.saturating_add(fee); - if balance < total_payment { + let fee = gas_price.saturating_mul(gas_limit); + let total_payment = value.saturating_add(fee); + + if account.balance < total_payment { return Err(eg!(format!( "InsufficientBalance, origin: {:?}, actual balance {}, but expected payment {}", - origin, balance, total_payment + origin, account.balance, total_payment ))); } diff --git a/src/components/contracts/modules/evm/Cargo.toml b/src/components/contracts/modules/evm/Cargo.toml index 6bac465ee..1b01e3e68 100644 --- a/src/components/contracts/modules/evm/Cargo.toml +++ b/src/components/contracts/modules/evm/Cargo.toml @@ -16,6 +16,7 @@ evm-runtime = { version = "0.35.0", default-features = false } evm-gasometer = { version = "0.30.0", default-features = false } ethereum = { version = "0.12.0", default-features = false, features = ["with-serde"] } impl-trait-for-tuples = "0.2" +log = "0.4" tracing = "0.1" rlp = { version = "0.5", default-features = false } ruc = "1.0" diff --git a/src/components/contracts/modules/evm/precompile/utils/Cargo.toml b/src/components/contracts/modules/evm/precompile/utils/Cargo.toml index 5a2091980..8deb7e314 100644 --- a/src/components/contracts/modules/evm/precompile/utils/Cargo.toml +++ b/src/components/contracts/modules/evm/precompile/utils/Cargo.toml @@ -13,3 +13,4 @@ tracing = "0.1" num_enum = { version = "0.5.3", default-features = false } precompile-utils-macro = { path = "macro" } sha3 = { version = "0.10", default-features = false } +module-evm = { path = "../../../../modules/evm"} diff --git a/src/components/contracts/modules/evm/src/impls.rs b/src/components/contracts/modules/evm/src/impls.rs index bf405846c..071d2a3d8 100644 --- a/src/components/contracts/modules/evm/src/impls.rs +++ b/src/components/contracts/modules/evm/src/impls.rs @@ -108,4 +108,11 @@ impl OnChargeEVMTransaction for App { C::AccountAsset::refund(ctx, &account_id, already_withdrawn)?; C::AccountAsset::burn(ctx, &account_id, corrected_fee) } + + fn pay_priority_fee(ctx: &Context, tip: U256) -> Result<()> { + let author = App::::find_proposer(ctx); + let account_id = C::AddressMapping::convert_to_account_id(author); + + C::AccountAsset::income(ctx, &account_id, tip) + } } diff --git a/src/components/contracts/modules/evm/src/lib.rs b/src/components/contracts/modules/evm/src/lib.rs index 3839482c3..23e11d9c0 100644 --- a/src/components/contracts/modules/evm/src/lib.rs +++ b/src/components/contracts/modules/evm/src/lib.rs @@ -33,7 +33,7 @@ use fp_evm::TransactionStatus; use evm::executor::stack::PrecompileSet as EvmPrecompileSet; use ethereum::{ - Log, ReceiptV0 as Receipt, TransactionAction, TransactionSignature, TransactionV0, + Log, ReceiptV0 as Receipt, TransactionAction, TransactionSignature, TransactionV2, }; use fp_types::{ @@ -110,7 +110,7 @@ impl App { _lowlevel: Vec, transaction_index: u32, transaction_hash: H256, - ) -> Result<(TransactionV0, TransactionStatus, Receipt)> { + ) -> Result<(TransactionV2, TransactionStatus, Receipt)> { let function = self.contracts.bridge.function("withdrawAsset").c(d!())?; let asset = Token::FixedBytes(Vec::from(_asset)); @@ -167,7 +167,7 @@ impl App { _lowlevel: Vec, transaction_index: u32, transaction_hash: H256, - ) -> Result<(TransactionV0, TransactionStatus, Receipt)> { + ) -> Result<(TransactionV2, TransactionStatus, Receipt)> { let function = self.contracts.bridge.function("withdrawFRA").c(d!())?; let from = Token::Bytes(from.noah_to_bytes()); @@ -251,13 +251,13 @@ impl App { from: H160, to: H160, logs: Vec, - ) -> (TransactionV0, TransactionStatus, Receipt) { + ) -> (TransactionV2, TransactionStatus, Receipt) { let signature_fake = H256([ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, ]); - let tx = TransactionV0 { + let tx = TransactionV2::Legacy(ethereum::LegacyTransaction { nonce: U256::zero(), gas_price, gas_limit, @@ -266,7 +266,7 @@ impl App { .unwrap(), input, action, - }; + }); let mut logs_bloom = Bloom::default(); Self::logs_bloom(&logs, &mut logs_bloom); diff --git a/src/components/contracts/modules/evm/src/runtime/runner.rs b/src/components/contracts/modules/evm/src/runtime/runner.rs index 7525ac9b1..0c45bad38 100644 --- a/src/components/contracts/modules/evm/src/runtime/runner.rs +++ b/src/components/contracts/modules/evm/src/runtime/runner.rs @@ -30,7 +30,8 @@ impl ActionRunner { source: H160, value: U256, gas_limit: u64, - gas_price: Option, + max_fee_per_gas: Option, + max_priority_fee_per_gas: Option, nonce: Option, config: &'config evm::Config, precompiles: &'precompiles C::PrecompilesType, @@ -46,30 +47,43 @@ impl ActionRunner { >, ) -> (ExitReason, R), { - let min_gas_price = C::FeeCalculator::min_gas_price(ctx.header.height as u64); + let base_fee = C::FeeCalculator::min_gas_price(ctx.header.height as u64); // Gas price check is skipped when performing a gas estimation. - let gas_price = match gas_price { - Some(gas_price) => { - ensure!(gas_price >= min_gas_price, "GasPriceTooLow"); - gas_price + let max_fee_per_gas = match max_fee_per_gas { + Some(max_fee_per_gas) => { + ensure!(max_fee_per_gas >= base_fee, "GasPriceTooLow"); + max_fee_per_gas } None => Default::default(), }; let vicinity = Vicinity { - gas_price, + gas_price: max_fee_per_gas, origin: source, }; let metadata = StackSubstateMetadata::new(gas_limit, config); - let state = FindoraStackState::new(ctx, &vicinity, metadata); + let state = FindoraStackState::::new(ctx, &vicinity, metadata); let mut executor = StackExecutor::new_with_precompiles(state, config, precompiles); - let total_fee = gas_price + // After eip-1559 we make sure the account can pay both the evm execution and priority fees. + let max_base_fee = max_fee_per_gas .checked_mul(U256::from(gas_limit)) .ok_or(eg!("FeeOverflow"))?; + let max_priority_fee = if let Some(max_priority_fee) = max_priority_fee_per_gas { + max_priority_fee + .checked_mul(U256::from(gas_limit)) + .ok_or(eg!("FeeOverflow"))? + } else { + U256::zero() + }; + + let total_fee = max_base_fee + .checked_add(max_priority_fee) + .ok_or(eg!("FeeOverflow"))?; + let total_payment = value.checked_add(total_fee).ok_or(eg!("PaymentOverflow"))?; let source_account = App::::account_basic(ctx, &source); @@ -83,7 +97,6 @@ impl ActionRunner { ) ); } - if !config.estimate { ensure!(source_account.balance >= total_payment, "BalanceLow"); @@ -95,27 +108,60 @@ impl ActionRunner { let (reason, retv) = f(&mut executor); let used_gas = U256::from(executor.used_gas()); - let actual_fee = executor.fee(gas_price); - tracing::debug!( + let (actual_fee, actual_priority_fee) = + if let Some(max_priority_fee) = max_priority_fee_per_gas { + let actual_priority_fee = max_priority_fee + .checked_mul(used_gas) + .ok_or(eg!("FeeOverflow"))?; + let actual_fee = executor + .fee(base_fee) + .checked_add(actual_priority_fee) + .unwrap_or_else(U256::max_value); + (actual_fee, Some(actual_priority_fee)) + } else { + (executor.fee(base_fee), None) + }; + tracing::trace!( target: "evm", - "Execution {:?} [source: {:?}, value: {}, gas_price {}, gas_limit: {}, actual_fee: {}]", + "Execution {:?} [source: {:?}, value: {}, gas_limit: {}, actual_fee: {}]", reason, source, value, - gas_price, gas_limit, actual_fee ); - + // The difference between initially withdrawn and the actual cost is refunded. + // + // Considered the following request: + // +-----------+---------+--------------+ + // | Gas_limit | Max_Fee | Max_Priority | + // +-----------+---------+--------------+ + // | 20 | 10 | 6 | + // +-----------+---------+--------------+ + // + // And execution: + // +----------+----------+ + // | Gas_used | Base_Fee | + // +----------+----------+ + // | 5 | 2 | + // +----------+----------+ + // + // Initially withdrawn (10 + 6) * 20 = 320. + // Actual cost (2 + 6) * 5 = 40. + // Refunded 320 - 40 = 280. + // Tip 5 * 6 = 30. + // Burned 320 - (280 + 30) = 10. Which is equivalent to gas_used * base_fee. if !config.estimate { - // Refund fees to the `source` account if deducted more before, App::::correct_and_deposit_fee(ctx, &source, actual_fee, total_fee)?; + if let Some(actual_priority_fee) = actual_priority_fee { + App::::pay_priority_fee(ctx, actual_priority_fee)?; + } } let state = executor.into_state(); for address in state.substate.deletes { - tracing::debug!( + tracing::trace!( target: "evm", "Deleting account at {:?}", address @@ -269,13 +315,13 @@ impl Runner for ActionRunner { fn call(ctx: &Context, args: Call, config: &evm::Config) -> Result { let precompiles = C::PrecompilesValue::get(ctx.clone()); let access_list = Vec::new(); - Self::execute( ctx, args.source, args.value, args.gas_limit, - args.gas_price, + args.max_fee_per_gas, + args.max_priority_fee_per_gas, args.nonce, config, &precompiles, @@ -295,13 +341,13 @@ impl Runner for ActionRunner { fn create(ctx: &Context, args: Create, config: &evm::Config) -> Result { let precompiles = C::PrecompilesValue::get(ctx.clone()); let access_list = Vec::new(); - Self::execute( ctx, args.source, args.value, args.gas_limit, - args.gas_price, + args.max_fee_per_gas, + args.max_priority_fee_per_gas, args.nonce, config, &precompiles, @@ -309,7 +355,6 @@ impl Runner for ActionRunner { let address = executor.create_address(evm::CreateScheme::Legacy { caller: args.source, }); - ( executor .transact_create( @@ -334,13 +379,13 @@ impl Runner for ActionRunner { let code_hash = H256::from_slice(Keccak256::digest(&args.init).as_slice()); let precompiles = C::PrecompilesValue::get(ctx.clone()); let access_list = Vec::new(); - Self::execute( ctx, args.source, args.value, args.gas_limit, - args.gas_price, + args.max_fee_per_gas, + args.max_priority_fee_per_gas, args.nonce, config, &precompiles, diff --git a/src/components/contracts/modules/evm/tests/evm_integration.rs b/src/components/contracts/modules/evm/tests/evm_integration.rs index 7f6163ce2..14ae5db8a 100644 --- a/src/components/contracts/modules/evm/tests/evm_integration.rs +++ b/src/components/contracts/modules/evm/tests/evm_integration.rs @@ -287,6 +287,8 @@ fn test_balance_of_with_eth_call(contract: ERC20, who: H160) -> U256 { value: U256::zero(), gas_limit: DEFAULT_GAS_LIMIT, gas_price: None, + max_fee_per_gas: None, + max_priority_fee_per_gas: None, nonce: None, }; diff --git a/src/components/contracts/modules/template/tests/template_integration.rs b/src/components/contracts/modules/template/tests/template_integration.rs index 85c5f1587..34ff9615c 100644 --- a/src/components/contracts/modules/template/tests/template_integration.rs +++ b/src/components/contracts/modules/template/tests/template_integration.rs @@ -3,7 +3,7 @@ //! Template module integration tests. use abci::*; use fp_mocks::*; -use fp_traits::account::{AccountAsset, FeeCalculator}; +use fp_traits::{account::AccountAsset, evm::FeeCalculator}; use fp_types::{actions::template::Action as TemplateAction, actions::Action, U256}; use fp_utils::tx::EvmRawTxWrapper; use module_template::ValueStore; @@ -149,7 +149,9 @@ fn test_abci_commit() { &ALICE_XFR.pub_key.into() ), U256::from(100_0000_0000_0000_0000_u64).saturating_sub( - ::FeeCalculator::min_fee() + ::FeeCalculator::min_gas_price( + BASE_APP.lock().unwrap().deliver_state.header.height as u64, + ) ) ); } diff --git a/src/components/contracts/primitives/evm/src/lib.rs b/src/components/contracts/primitives/evm/src/lib.rs index 2b972ea60..62b37bda3 100644 --- a/src/components/contracts/primitives/evm/src/lib.rs +++ b/src/components/contracts/primitives/evm/src/lib.rs @@ -4,7 +4,9 @@ use ethereum_types::{Bloom, H160, H256, U256}; use evm::ExitReason; use fp_core::context::Context; -use fp_types::actions::evm::{Call, Create, Create2}; +use fp_types::actions::evm::{ + Call, Create, Create2, +}; use ruc::*; use serde::{Deserialize, Serialize}; diff --git a/src/components/contracts/primitives/mocks/src/lib.rs b/src/components/contracts/primitives/mocks/src/lib.rs index f88cac008..4eaed9676 100644 --- a/src/components/contracts/primitives/mocks/src/lib.rs +++ b/src/components/contracts/primitives/mocks/src/lib.rs @@ -7,7 +7,7 @@ pub use baseapp::{ }; pub use fp_types::{actions::Action, assemble::UncheckedTransaction}; -use ethereum::{TransactionAction, TransactionSignature, TransactionV0 as Transaction}; +use ethereum::{TransactionAction, TransactionSignature, TransactionV2 as Transaction}; use fp_traits::account::AccountAsset; use fp_traits::evm::{AddressMapping, EthereumAddressMapping}; use fp_types::crypto::{Address, MultiSignature}; @@ -148,7 +148,7 @@ impl UnsignedTransaction { ) .unwrap(); - Transaction { + Transaction::Legacy(ethereum::LegacyTransaction { nonce: self.nonce, gas_price: self.gas_price, gas_limit: self.gas_limit, @@ -156,6 +156,6 @@ impl UnsignedTransaction { value: self.value, input: self.input.clone(), signature: sig, - } + }) } } diff --git a/src/components/contracts/primitives/rpc-core/Cargo.toml b/src/components/contracts/primitives/rpc-core/Cargo.toml index 81617b82f..87ff9c686 100644 --- a/src/components/contracts/primitives/rpc-core/Cargo.toml +++ b/src/components/contracts/primitives/rpc-core/Cargo.toml @@ -9,6 +9,8 @@ description = "RPC traits of Ethereum." license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +rlp = "0.5" +ethereum = { version = "0.12.0", default-features = false, features = ["with-serde"] } ethereum-types = "0.13.1" futures = "0.3.16" jsonrpc-core = { git = "https://github.com/FindoraNetwork/jsonrpc.git", package = "jsonrpc-core" } diff --git a/src/components/contracts/primitives/rpc-core/src/types/block.rs b/src/components/contracts/primitives/rpc-core/src/types/block.rs index 5786136da..855ffa17f 100644 --- a/src/components/contracts/primitives/rpc-core/src/types/block.rs +++ b/src/components/contracts/primitives/rpc-core/src/types/block.rs @@ -90,6 +90,8 @@ pub struct Block { pub transactions: BlockTransactions, /// Size in bytes pub size: Option, + /// Base Fee for post-EIP1559 blocks. + pub base_fee_per_gas: Option, } /// Block header representation. diff --git a/src/components/contracts/primitives/rpc-core/src/types/call_request.rs b/src/components/contracts/primitives/rpc-core/src/types/call_request.rs index 0451dbaf6..2e965b9c9 100644 --- a/src/components/contracts/primitives/rpc-core/src/types/call_request.rs +++ b/src/components/contracts/primitives/rpc-core/src/types/call_request.rs @@ -31,6 +31,10 @@ pub struct CallRequest { pub to: Option, /// Gas Price pub gas_price: Option, + /// EIP-1559 Max base fee the caller is willing to pay + pub max_fee_per_gas: Option, + /// EIP-1559 Priority fee the caller is paying to the block author + pub max_priority_fee_per_gas: Option, /// Gas pub gas: Option, /// Value diff --git a/src/components/contracts/primitives/rpc-core/src/types/mod.rs b/src/components/contracts/primitives/rpc-core/src/types/mod.rs index daa204156..422f78580 100644 --- a/src/components/contracts/primitives/rpc-core/src/types/mod.rs +++ b/src/components/contracts/primitives/rpc-core/src/types/mod.rs @@ -56,5 +56,5 @@ pub use self::transaction::{ LocalTransactionStatus, PendingTransaction, PendingTransactions, RichRawTransaction, Transaction, }; -pub use self::transaction_request::TransactionRequest; +pub use self::transaction_request::{TransactionMessage, TransactionRequest}; pub use self::work::Work; diff --git a/src/components/contracts/primitives/rpc-core/src/types/receipt.rs b/src/components/contracts/primitives/rpc-core/src/types/receipt.rs index 5d1ed929e..846609176 100644 --- a/src/components/contracts/primitives/rpc-core/src/types/receipt.rs +++ b/src/components/contracts/primitives/rpc-core/src/types/receipt.rs @@ -54,4 +54,7 @@ pub struct Receipt { // NOTE(niklasad1): Unknown after EIP98 rules, if it's missing then skip serializing it #[serde(skip_serializing_if = "Option::is_none", rename = "status")] pub status_code: Option, + + /// Effective gas price. Pre-eip1559 this is just the gasprice. Post-eip1559 this is base fee + priority fee. + pub effective_gas_price: U256, } diff --git a/src/components/contracts/primitives/rpc-core/src/types/transaction.rs b/src/components/contracts/primitives/rpc-core/src/types/transaction.rs index 6d767f40c..d57e20f55 100644 --- a/src/components/contracts/primitives/rpc-core/src/types/transaction.rs +++ b/src/components/contracts/primitives/rpc-core/src/types/transaction.rs @@ -17,6 +17,7 @@ // along with this program. If not, see . use crate::types::Bytes; +use ethereum::{AccessListItem, TransactionV2}; use ethereum_types::{H160, H256, H512, U256, U64}; use serde::ser::SerializeStruct; use serde::{Serialize, Serializer}; @@ -46,7 +47,11 @@ pub struct Transaction { /// Transfered value pub value: U256, /// Gas Price - pub gas_price: U256, + pub gas_price: Option, + /// eip1559. Max BaseFeePerGas the user is willing to pay. + pub max_fee_per_gas: Option, + /// eip1559.The miner's tip. + pub max_priority_fee_per_gas: Option, /// Gas pub gas: U256, /// Data @@ -67,6 +72,67 @@ pub struct Transaction { pub r: U256, /// The S field of the signature. pub s: U256, + /// eip1559. Pre-pay to warm storage access. + pub access_list: Option>, +} + +impl From for Transaction { + fn from(transaction: TransactionV2) -> Self { + let serialized = rlp::encode(&transaction); + let hash = transaction.hash(); + let raw = Bytes(serialized.to_vec()); + match transaction { + TransactionV2::Legacy(t) => Transaction { + hash, + nonce: t.nonce, + block_hash: None, + block_number: None, + transaction_index: None, + from: H160::default(), + to: None, + value: t.value, + gas_price: Some(t.gas_price), + max_fee_per_gas: Some(t.gas_price), + max_priority_fee_per_gas: Some(t.gas_price), + gas: t.gas_limit, + input: Bytes(t.clone().input), + creates: None, + raw, + public_key: None, + chain_id: t.signature.chain_id().map(U64::from), + standard_v: U256::from(t.signature.standard_v()), + v: U256::from(t.signature.v()), + r: U256::from(t.signature.r().as_bytes()), + s: U256::from(t.signature.s().as_bytes()), + access_list: None, + }, + TransactionV2::EIP1559(t) => Transaction { + hash, + nonce: t.nonce, + block_hash: None, + block_number: None, + transaction_index: None, + from: H160::default(), + to: None, + value: t.value, + gas_price: None, + max_fee_per_gas: Some(t.max_fee_per_gas), + max_priority_fee_per_gas: Some(t.max_priority_fee_per_gas), + gas: t.gas_limit, + input: Bytes(t.clone().input), + creates: None, + raw, + public_key: None, + chain_id: Some(U64::from(t.chain_id)), + standard_v: U256::from(t.odd_y_parity as u8), + v: U256::from(t.odd_y_parity as u8), + r: U256::from(t.r.as_bytes()), + s: U256::from(t.s.as_bytes()), + access_list: Some(t.access_list), + }, + _ => Transaction::default(), + } + } } /// Local Transaction Status diff --git a/src/components/contracts/primitives/rpc-core/src/types/transaction_request.rs b/src/components/contracts/primitives/rpc-core/src/types/transaction_request.rs index bbddf8d5f..b4099b43f 100644 --- a/src/components/contracts/primitives/rpc-core/src/types/transaction_request.rs +++ b/src/components/contracts/primitives/rpc-core/src/types/transaction_request.rs @@ -22,8 +22,15 @@ use crate::types::Bytes; use ethereum_types::{H160, U256}; use serde::{Deserialize, Serialize}; +use ethereum::{AccessListItem, EIP1559TransactionMessage, LegacyTransactionMessage}; + +pub enum TransactionMessage { + Legacy(LegacyTransactionMessage), + EIP1559(EIP1559TransactionMessage), +} + /// Transaction request coming from RPC -#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Serialize, Deserialize)] +#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize)] #[serde(deny_unknown_fields)] #[serde(rename_all = "camelCase")] pub struct TransactionRequest { @@ -33,6 +40,10 @@ pub struct TransactionRequest { pub to: Option, /// Gas Price pub gas_price: Option, + /// Max BaseFeePerGas the user is willing to pay. + pub max_fee_per_gas: Option, + /// The miner's tip. + pub max_priority_fee_per_gas: Option, /// Gas pub gas: Option, /// Value of transaction in wei @@ -41,4 +52,53 @@ pub struct TransactionRequest { pub data: Option, /// Transaction's nonce pub nonce: Option, + /// Pre-pay to warm storage access. + pub access_list: Option>, +} + +impl From for Option { + fn from(val: TransactionRequest) -> Option { + match (val.gas_price, val.max_fee_per_gas, val.access_list.clone()) { + // Legacy + (Some(_), None, None) => { + Some(TransactionMessage::Legacy(LegacyTransactionMessage { + nonce: U256::zero(), + gas_price: val.gas_price.unwrap_or_default(), + gas_limit: val.gas.unwrap_or_default(), + value: val.value.unwrap_or(U256::zero()), + input: val.data.map(|s| s.into_vec()).unwrap_or_default(), + action: match val.to { + Some(to) => ethereum::TransactionAction::Call(to), + None => ethereum::TransactionAction::Create, + }, + chain_id: None, + })) + } + // EIP1559 + (None, Some(_), _) | (None, None, None) => { + // Empty fields fall back to the canonical transaction schema. + Some(TransactionMessage::EIP1559(EIP1559TransactionMessage { + nonce: U256::zero(), + max_fee_per_gas: val.max_fee_per_gas.unwrap_or_default(), + max_priority_fee_per_gas: val + .max_priority_fee_per_gas + .unwrap_or_else(|| U256::from(0)), + gas_limit: val.gas.unwrap_or_default(), + value: val.value.unwrap_or(U256::zero()), + input: val.data.map(|s| s.into_vec()).unwrap_or_default(), + action: match val.to { + Some(to) => ethereum::TransactionAction::Call(to), + None => ethereum::TransactionAction::Create, + }, + chain_id: 0, + access_list: val + .access_list + .unwrap_or_default() + .into_iter() + .collect(), + })) + } + _ => None, + } + } } diff --git a/src/components/contracts/primitives/traits/src/account.rs b/src/components/contracts/primitives/traits/src/account.rs index 65bb14fd1..2397b0e1d 100644 --- a/src/components/contracts/primitives/traits/src/account.rs +++ b/src/components/contracts/primitives/traits/src/account.rs @@ -56,15 +56,6 @@ pub trait AccountAsset
{ spender: &Address, amount: U256, ) -> Result<()>; -} - -/// Outputs the current transaction fee. -pub trait FeeCalculator { - fn min_fee() -> U256; -} -impl FeeCalculator for () { - fn min_fee() -> U256 { - U256::zero() - } + fn income(ctx: &Context, who: &Address, value: U256) -> Result<()>; } diff --git a/src/components/contracts/primitives/traits/src/base.rs b/src/components/contracts/primitives/traits/src/base.rs index b25b35e35..1f11400ab 100644 --- a/src/components/contracts/primitives/traits/src/base.rs +++ b/src/components/contracts/primitives/traits/src/base.rs @@ -1,4 +1,4 @@ -use ethereum::{BlockV0 as Block, ReceiptV0 as Receipt}; +use ethereum::{BlockV2 as Block, ReceiptV0 as Receipt}; use fp_core::account::SmartAccount; use fp_evm::BlockId; use fp_types::crypto::Address; diff --git a/src/components/contracts/primitives/traits/src/evm.rs b/src/components/contracts/primitives/traits/src/evm.rs index 7e6d000fd..4260c8991 100644 --- a/src/components/contracts/primitives/traits/src/evm.rs +++ b/src/components/contracts/primitives/traits/src/evm.rs @@ -81,4 +81,7 @@ pub trait OnChargeEVMTransaction { corrected_fee: U256, already_withdrawn: U256, ) -> Result<()>; + + /// Introduced in EIP1559 to handle the priority tip payment to the block Author. + fn pay_priority_fee(ctx: &Context, tip: U256) -> Result<()>; } diff --git a/src/components/contracts/primitives/types/src/actions/ethereum.rs b/src/components/contracts/primitives/types/src/actions/ethereum.rs index 5d2403a08..4e5ab9fc8 100644 --- a/src/components/contracts/primitives/types/src/actions/ethereum.rs +++ b/src/components/contracts/primitives/types/src/actions/ethereum.rs @@ -1,4 +1,4 @@ -use ethereum::TransactionV0 as Transaction; +use ethereum::TransactionV2 as Transaction; use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] diff --git a/src/components/contracts/primitives/types/src/actions/evm.rs b/src/components/contracts/primitives/types/src/actions/evm.rs index 378d06a6d..39f2e6207 100644 --- a/src/components/contracts/primitives/types/src/actions/evm.rs +++ b/src/components/contracts/primitives/types/src/actions/evm.rs @@ -16,6 +16,8 @@ pub struct Call { pub value: U256, pub gas_limit: u64, pub gas_price: Option, + pub max_fee_per_gas: Option, + pub max_priority_fee_per_gas: Option, pub nonce: Option, } @@ -26,6 +28,8 @@ pub struct Create { pub value: U256, pub gas_limit: u64, pub gas_price: Option, + pub max_fee_per_gas: Option, + pub max_priority_fee_per_gas: Option, pub nonce: Option, } @@ -37,5 +41,7 @@ pub struct Create2 { pub value: U256, pub gas_limit: u64, pub gas_price: Option, + pub max_fee_per_gas: Option, + pub max_priority_fee_per_gas: Option, pub nonce: Option, } diff --git a/src/components/contracts/primitives/types/src/assemble.rs b/src/components/contracts/primitives/types/src/assemble.rs index 41cdb5a16..3ea03b3e2 100644 --- a/src/components/contracts/primitives/types/src/assemble.rs +++ b/src/components/contracts/primitives/types/src/assemble.rs @@ -2,7 +2,7 @@ use crate::actions::ethereum::Action as EtherAction; use crate::actions::Action; use crate::crypto::{Address, Signature}; use crate::transaction; -use ethereum::TransactionV0 as Transaction; +use ethereum::TransactionV2 as Transaction; use primitive_types::U256; use ruc::*; use serde::{Deserialize, Serialize}; diff --git a/src/components/contracts/primitives/utils/Cargo.toml b/src/components/contracts/primitives/utils/Cargo.toml index 672f13389..8ad50470c 100644 --- a/src/components/contracts/primitives/utils/Cargo.toml +++ b/src/components/contracts/primitives/utils/Cargo.toml @@ -9,6 +9,8 @@ description = "Findora Primitive utility functions" readme = "README.md" [dependencies] +ethereum = { version = "0.12.0", default-features = false, features = ["with-serde"] } +ethereum-types = { version = "0.13.1", default-features = false } futures = "0.3.16" base64 = "0.13" bip0039 = "0.8.0" diff --git a/src/components/contracts/primitives/wasm/Cargo.toml b/src/components/contracts/primitives/wasm/Cargo.toml index 7a35e137b..e4318191c 100644 --- a/src/components/contracts/primitives/wasm/Cargo.toml +++ b/src/components/contracts/primitives/wasm/Cargo.toml @@ -22,7 +22,7 @@ rlp = "0.5" ruc = "1.0" sha3 = "0.10" serde_json = "1.0" -wasm-bindgen = { version = "=0.2.73", features = ["serde-serialize"] } +wasm-bindgen = { version = "0.2.83", features = ["serde-serialize"] } # Must enable the "js"-feature, # OR the compiling will fail. diff --git a/src/components/contracts/primitives/wasm/src/wasm.rs b/src/components/contracts/primitives/wasm/src/wasm.rs index f587e244c..846f97c04 100644 --- a/src/components/contracts/primitives/wasm/src/wasm.rs +++ b/src/components/contracts/primitives/wasm/src/wasm.rs @@ -1,12 +1,11 @@ #![allow(clippy::unused_unit)] use core::fmt::Display; -use ethereum::{LegacyTransactionMessage, TransactionV0 as Transaction}; +use ethereum::TransactionV2 as Transaction; use ethereum_types::{H160, H256}; use fp_types::{ actions::{ethereum::Action as EthAction, Action}, assemble::UncheckedTransaction, - crypto::secp256k1_ecdsa_recover, }; use fp_utils::tx::EvmRawTxWrapper; use ruc::{d, err::RucResult}; @@ -22,12 +21,28 @@ pub(crate) fn error_to_jsvalue(e: T) -> JsValue { pub fn recover_signer(transaction: &Transaction) -> Option { let mut sig = [0u8; 65]; let mut msg = [0u8; 32]; - sig[0..32].copy_from_slice(&transaction.signature.r()[..]); - sig[32..64].copy_from_slice(&transaction.signature.s()[..]); - sig[64] = transaction.signature.standard_v(); - msg.copy_from_slice(&LegacyTransactionMessage::from(transaction.clone()).hash()[..]); - - let pubkey = secp256k1_ecdsa_recover(&sig, &msg).ok()?; + match transaction { + Transaction::Legacy(t) => { + sig[0..32].copy_from_slice(&t.signature.r()[..]); + sig[32..64].copy_from_slice(&t.signature.s()[..]); + sig[64] = t.signature.standard_v(); + msg.copy_from_slice( + ðereum::LegacyTransactionMessage::from(t.clone()).hash()[..], + ); + } + Transaction::EIP1559(t) => { + sig[0..32].copy_from_slice(&t.r[..]); + sig[32..64].copy_from_slice(&t.s[..]); + sig[64] = t.odd_y_parity as u8; + msg.copy_from_slice( + ðereum::EIP1559TransactionMessage::from(t.clone()).hash()[..], + ); + } + _ => { + return None; + } + } + let pubkey = fp_types::crypto::secp256k1_ecdsa_recover(&sig, &msg).ok()?; Some(H160::from(H256::from_slice( Keccak256::digest(pubkey).as_slice(), ))) @@ -77,20 +92,19 @@ pub fn evm_tx_hash(raw_tx: String) -> Result { #[allow(missing_docs)] mod test { use super::*; - use fp_types::actions::Action; + use fp_types::actions::{ethereum::Action as EthAction, Action}; #[test] fn recover_signer_works() { - let raw_tx = String::from("ZXZtOnsic2lnbmF0dXJlIjpudWxsLCJmdW5jdGlvbiI6eyJFdGhlcmV1bSI6eyJUcmFuc2FjdCI6eyJub25jZSI6IjB4MSIsImdhc19wcmljZSI6IjB4MTc0ODc2ZTgwMCIsImdhc19saW1pdCI6IjB4NTIwOCIsImFjdGlvbiI6eyJDYWxsIjoiMHgyYWQzMjg0NmM2ZGQyZmZkM2VkYWRiZTUxY2Q1YWUwNGFhNWU1NzVlIn0sInZhbHVlIjoiMHg1NmJjNzVlMmQ2MzEwMDAwMCIsImlucHV0IjpbXSwic2lnbmF0dXJlIjp7InYiOjEwODIsInIiOiIweGY4YWVmN2Y4MDUzZDg5ZmVlMzk1MGM0ZDcwMjA4MGJmM2E4MDcyYmVkNWQ4NGEzYWYxOWEzNjAwODFiNjM2YTIiLCJzIjoiMHgyOTYyOTlhOGYyNDMwYjg2ZmQzZWI5NzZlYWJjNzMwYWMxY2ZiYmJlMzZlYjY5ZWFlMzM4Y2ZmMzNjNGE5OGMxIn19fX19"); + let raw_tx = String::from("ZXZtOnsiRXRoZXJldW0iOnsiVHJhbnNhY3QiOnsiRUlQMTU1OSI6eyJjaGFpbl9pZCI6MjE1Miwibm9uY2UiOiIweDEiLCJtYXhfcHJpb3JpdHlfZmVlX3Blcl9nYXMiOiIweDI3MTAiLCJtYXhfZmVlX3Blcl9nYXMiOiIweDI3MTAiLCJnYXNfbGltaXQiOiIweDI3MTAiLCJhY3Rpb24iOnsiQ2FsbCI6IjB4MmFkMzI4NDZjNmRkMmZmZDNlZGFkYmU1MWNkNWFlMDRhYTVlNTc1ZSJ9LCJ2YWx1ZSI6IjB4MjcxMCIsImlucHV0IjpbXSwiYWNjZXNzX2xpc3QiOltdLCJvZGRfeV9wYXJpdHkiOmZhbHNlLCJyIjoiMHhmOGFlZjdmODA1M2Q4OWZlZTM5NTBjNGQ3MDIwODBiZjNhODA3MmJlZDVkODRhM2FmMTlhMzYwMDgxYjYzNmEyIiwicyI6IjB4Mjk2Mjk5YThmMjQzMGI4NmZkM2ViOTc2ZWFiYzczMGFjMWNmYmJiZTM2ZWI2OWVhZTMzOGNmZjMzYzRhOThjMSJ9fX19"); let tx_bytes = base64::decode_config(raw_tx, base64::URL_SAFE).unwrap(); let evm_tx = EvmRawTxWrapper::unwrap(&tx_bytes).unwrap(); - let unchecked_tx: UncheckedTransaction<()> = - serde_json::from_slice(evm_tx).unwrap(); - if let Action::Ethereum(EthAction::Transact(tx)) = unchecked_tx.function { + let action: Action = serde_json::from_slice(evm_tx).unwrap(); + if let Action::Ethereum(EthAction::Transact(tx)) = action { let signer = recover_signer(&tx).unwrap(); assert_eq!( format!("{:?}", signer), - "0xa5225cbee5052100ec2d2d94aa6d258558073757" + "0x7bc371bb41545d62117591e5051be3d2c6296f3e" ); } else { panic!() @@ -98,8 +112,9 @@ mod test { } #[test] + // LegacyTransaction fn evm_tx_hash_works() { - let raw_tx = String::from("eyJzaWduYXR1cmUiOm51bGwsImZ1bmN0aW9uIjp7IkV0aGVyZXVtIjp7IlRyYW5zYWN0Ijp7Im5vbmNlIjoiMHg5IiwiZ2FzX3ByaWNlIjoiMHhlOGQ0YTUxMDAwIiwiZ2FzX2xpbWl0IjoiMHg1MjA4IiwiYWN0aW9uIjp7IkNhbGwiOiIweGE1MjI1Y2JlZTUwNTIxMDBlYzJkMmQ5NGFhNmQyNTg1NTgwNzM3NTcifSwidmFsdWUiOiIweDk4YTdkOWI4MzE0YzAwMDAiLCJpbnB1dCI6W10sInNpZ25hdHVyZSI6eyJ2IjoxMDgyLCJyIjoiMHg4MDBjZjQ5ZTAzMmJhYzY4MjY3MzdhZGJhZDEzN2Y0MTk5OTRjNjgxZWE1ZDUyYjliMGJhZDJmNDAyYjMwMTI0IiwicyI6IjB4Mjk1Mjc3ZWY2NTYzNDAwY2VkNjFiODhkM2ZiNGM3YjMyY2NkNTcwYThiOWJiOGNiYmUyNTkyMTRhYjdkZTI1YSJ9fX19fQ=="); + let raw_tx = String::from("eyJzaWduYXR1cmUiOm51bGwsImZ1bmN0aW9uIjp7IkV0aGVyZXVtIjp7IlRyYW5zYWN0Ijp7IkxlZ2FjeSI6eyJub25jZSI6IjB4MCIsImdhc19wcmljZSI6IjB4MjU0MGJlNDAwIiwiZ2FzX2xpbWl0IjoiMHgxMDAwMDAiLCJhY3Rpb24iOnsiQ2FsbCI6IjB4MzMyNWE3ODQyNWYxN2E3ZTQ4N2ViNTY2NmIyYmZkOTNhYmIwNmM3MCJ9LCJ2YWx1ZSI6IjB4YSIsImlucHV0IjpbXSwic2lnbmF0dXJlIjp7InYiOjQzNDAsInIiOiIweDZiMjBjNzIzNTEzOTk4ZThmYTQ4NWM1MmI4ZjlhZTRmZDdiMWUwYmQwZGZiNzk4NTIzMThiMGMxMDBlOTFmNWUiLCJzIjoiMHg0ZDRjOGMxZjJlMTdjMDJjNGE4OTZlMjYyMTI3YjhiZDZlYmZkNWY1YTc1NWEzZTkyMjBjZmM2OGI4YzY5ZDVkIn19fX19fQ=="); let tx_bytes = base64::decode_config(raw_tx, base64::URL_SAFE).unwrap(); let unchecked_tx: UncheckedTransaction<()> = serde_json::from_slice(tx_bytes.as_slice()).unwrap(); @@ -107,7 +122,7 @@ mod test { let hash = H256::from_slice(Keccak256::digest(&rlp::encode(&tx)).as_slice()); assert_eq!( format!("{:?}", hash), - "0x0eeb0ff455b1b57b821634cf853e7247e584a675610f13097cc49c2022505df3" + "0x83901d025accca27ee53fdf1ee354f4437418731e0995ee031beb99499405d26" ); } else { panic!() diff --git a/src/components/contracts/rpc/src/eth.rs b/src/components/contracts/rpc/src/eth.rs index 5f572cb1b..a4781b3c2 100644 --- a/src/components/contracts/rpc/src/eth.rs +++ b/src/components/contracts/rpc/src/eth.rs @@ -7,16 +7,17 @@ use crate::{error_on_execution_failure, internal_err}; use baseapp::{extensions::SignedExtra, BaseApp}; use config::abci::global_cfg::CFG; use ethereum::{ - BlockV0 as EthereumBlock, LegacyTransactionMessage as EthereumTransactionMessage, - TransactionV0 as EthereumTransaction, + BlockV2 as EthereumBlock, + // LegacyTransactionMessage as EthereumTransactionMessage, + TransactionV2 as EthereumTransaction, }; use ethereum_types::{BigEndianHash, Bloom, H160, H256, H512, H64, U256, U64}; use evm::{ExitError, ExitReason}; use fp_evm::{BlockId, Runner, TransactionStatus}; use fp_rpc_core::types::{ Block, BlockNumber, BlockTransactions, Bytes, CallRequest, Filter, FilteredParams, - Index, Log, Receipt, Rich, RichBlock, SyncStatus, Transaction, TransactionRequest, - Work, + Index, Log, Receipt, Rich, RichBlock, SyncStatus, Transaction, TransactionMessage, + TransactionRequest, Work, }; use fp_rpc_core::EthApi; use fp_traits::{ @@ -179,28 +180,6 @@ impl EthApi for EthApiImpl { Ok(Some(::ChainId::get().into())) } - // let curr_height = match self.block_number() { - // Ok(h) => h.as_u64(), - // Err(e) => return Box::pin(future::err(e)), - // }; - - // let message = EthereumTransactionMessage { - // nonce, - // gas_price: request.gas_price.unwrap_or_else(|| { - // ::FeeCalculator::min_gas_price( - // curr_height, - // ) - // }), - // gas_limit: request.gas.unwrap_or_else(U256::max_value), - // value: request.value.unwrap_or_else(U256::zero), - // input: request.data.map(|s| s.into_vec()).unwrap_or_default(), - // action: match request.to { - // Some(to) => ethereum::TransactionAction::Call(to), - // None => ethereum::TransactionAction::Create, - // }, - // chain_id: chain_id.map(|s| s.as_u64()), - // }; - fn accounts(&self) -> Result> { self.accounts_sync() } @@ -256,30 +235,63 @@ impl EthApi for EthApiImpl { }; let chain_id = match self.chain_id() { - Ok(chain_id) => chain_id, + Ok(Some(chain_id)) => chain_id.as_u64(), + Ok(None) => { + return Box::pin(future::err(internal_err("chain id not available"))) + } Err(e) => return Box::pin(future::err(e)), }; + // let hash = self.client.info().best_hash; let curr_height = match self.block_number() { Ok(h) => h.as_u64(), Err(e) => return Box::pin(future::err(e)), }; - let message = EthereumTransactionMessage { - nonce, - gas_price: request.gas_price.unwrap_or_else(|| { - ::FeeCalculator::min_gas_price( - curr_height, - ) - }), - gas_limit: request.gas.unwrap_or_else(U256::max_value), - value: request.value.unwrap_or_else(U256::zero), - input: request.data.map(|s| s.into_vec()).unwrap_or_default(), - action: match request.to { - Some(to) => ethereum::TransactionAction::Call(to), - None => ethereum::TransactionAction::Create, - }, - chain_id: chain_id.map(|s| s.as_u64()), + let gas_price = request.gas_price.unwrap_or_else(|| { + ::FeeCalculator::min_gas_price(curr_height) + }); + let block = self.account_base_app.read().current_block(None); + let gas_limit = match request.gas { + Some(gas_limit) => gas_limit, + None => { + if let Some(block) = block { + block.header.gas_limit + } else { + ::BlockGasLimit::get() + } + } + }; + + let max_fee_per_gas = request.max_fee_per_gas; + + let message: Option = request.into(); + let message = match message { + Some(TransactionMessage::Legacy(mut m)) => { + m.nonce = nonce; + m.chain_id = Some(chain_id); + m.gas_limit = gas_limit; + m.gas_price = gas_price; + TransactionMessage::Legacy(m) + } + Some(TransactionMessage::EIP1559(mut m)) => { + if CFG.checkpoint.enable_eip1559_height > curr_height { + return Box::pin(future::err(internal_err(format!( + "eip1559 not enabled at height: {:?}", + curr_height + )))); + } + m.nonce = nonce; + m.chain_id = chain_id; + m.gas_limit = gas_limit; + if max_fee_per_gas.is_none() { + m.max_fee_per_gas = self.gas_price().unwrap_or_default(); + } + TransactionMessage::EIP1559(m) + } + _ => { + return Box::pin(future::err(internal_err("Transaction Type Error"))); + } }; let mut transaction = None; @@ -301,8 +313,8 @@ impl EthApi for EthApiImpl { return Box::pin(future::err(internal_err("no signer available"))); } }; - let transaction_hash = - H256::from_slice(Keccak256::digest(&rlp::encode(&transaction)).as_slice()); + let transaction_hash = transaction.hash(); + let function = actions::Action::Ethereum(actions::ethereum::Action::Transact(transaction)); let txn = serde_json::to_vec( @@ -352,12 +364,28 @@ impl EthApi for EthApiImpl { from, to, gas_price, + max_fee_per_gas, + max_priority_fee_per_gas, gas, value, data, nonce, } = request; + let _is_eip1559 = max_fee_per_gas.is_some() + && max_priority_fee_per_gas.is_some() + && max_fee_per_gas.unwrap() > U256::from(0) + && max_priority_fee_per_gas.unwrap() > U256::from(0); + + let (gas_price, _max_fee_per_gas, _max_priority_fee_per_gas) = { + let details = fee_details(gas_price, None, None)?; + ( + details.gas_price, + details.max_fee_per_gas, + details.max_priority_fee_per_gas, + ) + }; + let block = account_base_app.read().current_block(None); // use given gas limit or query current block's limit let gas_limit = match gas { @@ -399,6 +427,8 @@ impl EthApi for EthApiImpl { value: value.unwrap_or_default(), gas_limit: gas_limit.as_u64(), gas_price, + max_fee_per_gas: None, + max_priority_fee_per_gas: None, nonce, }; @@ -421,6 +451,8 @@ impl EthApi for EthApiImpl { value: value.unwrap_or_default(), gas_limit: gas_limit.as_u64(), gas_price, + max_fee_per_gas: None, + max_priority_fee_per_gas: None, nonce, }; @@ -538,12 +570,19 @@ impl EthApi for EthApiImpl { .read() .current_transaction_statuses(Some(BlockId::Hash(hash))); + let base_fee = block.as_ref().map(|b| { + ::FeeCalculator::min_gas_price( + b.header.number.as_u64(), + ) + }); + match (block, statuses) { (Some(block), Some(statuses)) => Ok(Some(rich_block_build( block, statuses.into_iter().map(Some).collect(), Some(hash), full, + base_fee, ))), _ => Ok(None), } @@ -582,6 +621,12 @@ impl EthApi for EthApiImpl { let block = account_base_app.read().current_block(id.clone()); let statuses = account_base_app.read().current_transaction_statuses(id); + let base_fee = block.as_ref().map(|b| { + ::FeeCalculator::min_gas_price( + b.header.number.as_u64(), + ) + }); + match (block, statuses) { (Some(block), Some(statuses)) => { let hash = block.header.hash(); @@ -591,9 +636,18 @@ impl EthApi for EthApiImpl { statuses.into_iter().map(Some).collect(), Some(hash), full, + base_fee, ))) } - _ => Ok(None), + _ => Ok(if let Some(h) = height { + if 0 < h && h < *EVM_FIRST_BLOCK_HEIGHT { + Some(dummy_block(h, full)) + } else { + None + } + } else { + None + }), } }); @@ -717,16 +771,54 @@ impl EthApi for EthApiImpl { } fn send_raw_transaction(&self, bytes: Bytes) -> BoxFuture> { - let transaction = match rlp::decode::(&bytes.0[..]) { - Ok(transaction) => transaction, - Err(_) => { - return Box::pin(future::err(internal_err("decode transaction failed"))); + let slice = &bytes.0[..]; + if slice.is_empty() { + return Box::pin(future::err(internal_err("transaction data is empty"))); + } + // let first = slice.get(0).unwrap(); + let first = slice.first().unwrap(); + let transaction = if first > &0x7f { + // Legacy transaction. Decode and wrap in envelope. + match rlp::decode::(slice) { + Ok(transaction) => ethereum::TransactionV2::Legacy(transaction), + Err(_) => { + return Box::pin(future::err(internal_err( + "decode transaction failed", + ))); + } + } + } else { + let curr_height = match self.block_number() { + Ok(h) => h.as_u64(), + Err(e) => return Box::pin(future::err(e)), + }; + + if CFG.checkpoint.enable_eip1559_height > curr_height { + return Box::pin(future::err(internal_err(format!( + "eip1559 not enabled at height: {:?}", + curr_height + )))); + } + // Typed Transaction. + // `ethereum` crate decode implementation for `TransactionV2` expects a valid rlp input, + // and EIP-1559 breaks that assumption by prepending a version byte. + // We re-encode the payload input to get a valid rlp, and the decode implementation will strip + // them to check the transaction version byte. + let extend = rlp::encode(&slice); + match rlp::decode::(&extend[..]) { + Ok(transaction) => transaction, + Err(_) => { + return Box::pin(future::err(internal_err( + "decode transaction failed", + ))) + } } }; + debug!(target: "eth_rpc", "send_raw_transaction :{:?}", transaction); - let transaction_hash = - H256::from_slice(Keccak256::digest(&rlp::encode(&transaction)).as_slice()); + let transaction_hash = transaction.hash(); + let function = actions::Action::Ethereum(actions::ethereum::Action::Transact(transaction)); let txn = serde_json::to_vec( @@ -764,6 +856,25 @@ impl EthApi for EthApiImpl { ) -> BoxFuture> { debug!(target: "eth_rpc", "estimate_gas, block number {:?} request:{:?}", number, request); + let _is_eip1559 = request.max_fee_per_gas.is_some() + && request.max_priority_fee_per_gas.is_some() + && request.max_fee_per_gas.unwrap() > U256::from(0) + && request.max_priority_fee_per_gas.unwrap() > U256::from(0); + + let (gas_price, _max_fee_per_gas, _max_priority_fee_per_gas) = { + if let Ok(details) = fee_details(request.gas_price, None, None) { + ( + details.gas_price, + details.max_fee_per_gas, + details.max_priority_fee_per_gas, + ) + } else { + return Box::pin(async move { + Err(internal_err("estimate_gas fee_details err!!!".to_string())) + }); + } + }; + let account_base_app = self.account_base_app.clone(); let task = spawn_blocking(move || { @@ -860,7 +971,9 @@ impl EthApi for EthApiImpl { let CallRequest { from, to, - gas_price, + gas_price: _, + max_fee_per_gas: _, + max_priority_fee_per_gas: _, gas, value, data, @@ -884,6 +997,8 @@ impl EthApi for EthApiImpl { value: value.unwrap_or_default(), gas_limit, gas_price, + max_fee_per_gas: None, + max_priority_fee_per_gas: None, nonce, }; @@ -908,6 +1023,8 @@ impl EthApi for EthApiImpl { value: value.unwrap_or_default(), gas_limit, gas_price, + max_fee_per_gas: None, + max_priority_fee_per_gas: None, nonce, }; @@ -1005,11 +1122,18 @@ impl EthApi for EthApiImpl { } } - Ok(Some(transaction_build( + let base_fee = Some( + ::FeeCalculator::min_gas_price( + block.header.number.as_u64(), + ), + ); + + Ok(transaction_build( block.transactions[index].clone(), Some(block), Some(statuses[index].clone()), - ))) + base_fee, + )) } _ => Ok(None), } @@ -1040,17 +1164,24 @@ impl EthApi for EthApiImpl { .read() .current_transaction_statuses(Some(BlockId::Hash(hash))); + let base_fee = block.as_ref().map(|b| { + ::FeeCalculator::min_gas_price( + b.header.number.as_u64(), + ) + }); + match (block, statuses) { (Some(block), Some(statuses)) => { if index >= block.transactions.len() { return Ok(None); } - Ok(Some(transaction_build( + Ok(transaction_build( block.transactions[index].clone(), Some(block), Some(statuses[index].clone()), - ))) + base_fee, + )) } _ => Ok(None), } @@ -1077,18 +1208,24 @@ impl EthApi for EthApiImpl { let index = index.value(); let block = account_base_app.read().current_block(id.clone()); let statuses = account_base_app.read().current_transaction_statuses(id); - match (block, statuses) { (Some(block), Some(statuses)) => { if index >= block.transactions.len() { return Ok(None); } - Ok(Some(transaction_build( + let base_fee = Some( + ::FeeCalculator::min_gas_price( + block.header.number.as_u64(), + ), + ); + + Ok(transaction_build( block.transactions[index].clone(), Some(block), Some(statuses[index].clone()), - ))) + base_fee, + )) } _ => Ok(None), } @@ -1121,8 +1258,14 @@ impl EthApi for EthApiImpl { .current_transaction_statuses(id.clone()); let receipts = account_base_app.read().current_receipts(id.clone()); - match (block, statuses, receipts) { - (Some(block), Some(statuses), Some(receipts)) => { + let base_fee = block.as_ref().map(|b| { + ::FeeCalculator::min_gas_price( + b.header.number.as_u64(), + ) + }); + + match (block, statuses, receipts, base_fee) { + (Some(block), Some(statuses), Some(receipts), Some(base_fee)) => { if id.is_none() { if let Some(idx) = statuses.iter().position(|t| t.transaction_hash == hash) @@ -1133,7 +1276,6 @@ impl EthApi for EthApiImpl { } } - let _leng = receipts.len(); let block_hash = H256::from_slice( Keccak256::digest(&rlp::encode(&block.header)).as_slice(), ); @@ -1143,6 +1285,15 @@ impl EthApi for EthApiImpl { cumulative_receipts .truncate((status.transaction_index + 1) as usize); + let transaction = block.transactions[index].clone(); + let effective_gas_price = match transaction { + EthereumTransaction::Legacy(t) => t.gas_price, + EthereumTransaction::EIP1559(t) => base_fee + .checked_add(t.max_priority_fee_per_gas) + .unwrap_or_else(U256::max_value), + EthereumTransaction::EIP2930(t) => t.gas_price, + }; + return Ok(Some(Receipt { transaction_hash: Some(status.transaction_hash), transaction_index: Some(status.transaction_index.into()), @@ -1196,6 +1347,7 @@ impl EthApi for EthApiImpl { status_code: Some(U64::from(receipt.state_root.to_low_u64_be())), logs_bloom: receipt.logs_bloom, state_root: None, + effective_gas_price, })); } _ => Ok(None), @@ -1307,33 +1459,62 @@ impl EthApi for EthApiImpl { } pub fn sign_transaction_message( - message: EthereumTransactionMessage, + message: TransactionMessage, private_key: &H256, ) -> ruc::Result { - let signing_message = libsecp256k1::Message::parse_slice(&message.hash()[..]) - .map_err(|_| eg!("invalid signing message"))?; - let secret = &libsecp256k1::SecretKey::parse_slice(&private_key[..]) - .map_err(|_| eg!("invalid secret"))?; - let (signature, recid) = libsecp256k1::sign(&signing_message, secret); - - let v = match message.chain_id { - None => 27 + recid.serialize() as u64, - Some(chain_id) => 2 * chain_id + 35 + recid.serialize() as u64, - }; - let rs = signature.serialize(); - let r = H256::from_slice(&rs[0..32]); - let s = H256::from_slice(&rs[32..64]); - - Ok(EthereumTransaction { - nonce: message.nonce, - gas_price: message.gas_price, - gas_limit: message.gas_limit, - action: message.action, - value: message.value, - input: message.input, - signature: ethereum::TransactionSignature::new(v, r, s) - .ok_or(eg!("signer generated invalid signature"))?, - }) + match message { + TransactionMessage::Legacy(m) => { + let signing_message = libsecp256k1::Message::parse_slice(&m.hash()[..]) + .map_err(|_| eg!("invalid signing message"))?; + let secret = &libsecp256k1::SecretKey::parse_slice(&private_key[..]) + .map_err(|_| eg!("invalid secret"))?; + let (signature, recid) = libsecp256k1::sign(&signing_message, secret); + + let v = match m.chain_id { + None => 27 + recid.serialize() as u64, + Some(chain_id) => 2 * chain_id + 35 + recid.serialize() as u64, + }; + let rs = signature.serialize(); + let r = H256::from_slice(&rs[0..32]); + let s = H256::from_slice(&rs[32..64]); + + Ok(EthereumTransaction::Legacy(ethereum::LegacyTransaction { + nonce: m.nonce, + gas_price: m.gas_price, + gas_limit: m.gas_limit, + action: m.action, + value: m.value, + input: m.input, + signature: ethereum::TransactionSignature::new(v, r, s) + .ok_or(eg!("signer generated invalid signature"))?, + })) + } + TransactionMessage::EIP1559(m) => { + let signing_message = libsecp256k1::Message::parse_slice(&m.hash()[..]) + .map_err(|_| eg!("invalid signing message"))?; + let secret = &libsecp256k1::SecretKey::parse_slice(&private_key[..]) + .map_err(|_| eg!("invalid secret"))?; + let (signature, recid) = libsecp256k1::sign(&signing_message, secret); + let rs = signature.serialize(); + let r = H256::from_slice(&rs[0..32]); + let s = H256::from_slice(&rs[32..64]); + + Ok(EthereumTransaction::EIP1559(ethereum::EIP1559Transaction { + chain_id: m.chain_id, + nonce: m.nonce, + max_priority_fee_per_gas: m.max_priority_fee_per_gas, + max_fee_per_gas: m.max_fee_per_gas, + gas_limit: m.gas_limit, + action: m.action, + value: m.value, + input: m.input.clone(), + access_list: m.access_list, + odd_y_parity: recid.serialize() != 0, + r, + s, + })) + } + } } fn rich_block_build( @@ -1341,6 +1522,7 @@ fn rich_block_build( statuses: Vec>, hash: Option, full_transactions: bool, + base_fee: Option, ) -> RichBlock { Rich { inner: Block { @@ -1376,11 +1558,12 @@ fn rich_block_build( .transactions .iter() .enumerate() - .map(|(index, transaction)| { + .filter_map(|(index, transaction)| { transaction_build( transaction.clone(), Some(block.clone()), Some(statuses[index].clone().unwrap_or_default()), + base_fee, ) }) .collect(), @@ -1403,82 +1586,141 @@ fn rich_block_build( } }, size: Some(U256::from(rlp::encode(&block).len() as u32)), + base_fee_per_gas: base_fee, }, extra_info: BTreeMap::new(), } } fn transaction_build( - transaction: EthereumTransaction, - block: Option, + ethereum_transaction: EthereumTransaction, + block: Option>, status: Option, -) -> Transaction { - let pubkey = match public_key(&transaction) { + base_fee: Option, +) -> Option { + let mut transaction: Transaction = ethereum_transaction.clone().into(); + + match ðereum_transaction { + EthereumTransaction::EIP1559(_) => { + if block.is_none() && status.is_none() { + transaction.gas_price = transaction.max_fee_per_gas; + } else { + let base_fee = base_fee.unwrap_or(U256::zero()); + let max_priority_fee_per_gas = + transaction.max_priority_fee_per_gas.unwrap_or(U256::zero()); + transaction.gas_price = Some( + base_fee + .checked_add(max_priority_fee_per_gas) + .unwrap_or_else(U256::max_value), + ); + } + } + EthereumTransaction::Legacy(_) => { + transaction.max_fee_per_gas = None; + transaction.max_priority_fee_per_gas = None; + } + _ => return None, + } + + let pubkey = match public_key(ðereum_transaction) { Ok(p) => Some(p), Err(_e) => None, }; - let hash = if let Some(status) = &status { + // Block hash. + // transaction.block_hash = block.as_ref().map_or(None, |block| { + // Some(H256::from_slice( + // Keccak256::digest(&rlp::encode(&block.header)).as_slice(), + // )) + // }); + transaction.block_hash = block.as_ref().map(|block| { + H256::from_slice(Keccak256::digest(&rlp::encode(&block.header)).as_slice()) + }); + + // Block number. + transaction.block_number = block.as_ref().map(|block| block.header.number); + // Transaction index. + + transaction.transaction_index = status + .as_ref() + .map(|status| U256::from(status.transaction_index)); + + transaction.from = status.as_ref().map_or( + { + match pubkey { + Some(pk) => { + H160::from(H256::from_slice(Keccak256::digest(pk).as_slice())) + } + _ => H160::default(), + } + }, + |status| status.from, + ); + // To. + transaction.to = status.as_ref().map_or( + { + let action = match ethereum_transaction.clone() { + EthereumTransaction::Legacy(t) => t.action, + EthereumTransaction::EIP1559(t) => t.action, + EthereumTransaction::EIP2930(t) => t.action, + }; + match action { + ethereum::TransactionAction::Call(to) => Some(to), + _ => None, + } + }, + |status| status.to, + ); + // Creates. + // transaction.creates = status + // .as_ref() + // .map_or(None, |status| status.contract_address); + transaction.creates = status.as_ref().and_then(|status| status.contract_address); + + // Public key. + transaction.public_key = pubkey.as_ref().map(H512::from); + + transaction.hash = if let Some(status) = &status { status.transaction_hash } else { - H256::from_slice(Keccak256::digest(&rlp::encode(&transaction)).as_slice()) + match ethereum_transaction { + EthereumTransaction::Legacy(t) => { + H256::from_slice(Keccak256::digest(&rlp::encode(&t)).as_slice()) + } + EthereumTransaction::EIP1559(t) => { + H256::from_slice(Keccak256::digest(&rlp::encode(&t)).as_slice()) + } + EthereumTransaction::EIP2930(_) => return None, + } }; - Transaction { - hash, - nonce: transaction.nonce, - block_hash: block.as_ref().map(|block| { - H256::from_slice(Keccak256::digest(&rlp::encode(&block.header)).as_slice()) - }), - block_number: block.as_ref().map(|block| block.header.number), - transaction_index: status - .as_ref() - .map(|status| U256::from(status.transaction_index)), - from: status.as_ref().map_or( - { - match pubkey { - Some(pk) => { - H160::from(H256::from_slice(Keccak256::digest(pk).as_slice())) - } - _ => H160::default(), - } - }, - |status| status.from, - ), - to: status.as_ref().map_or( - { - match transaction.action { - ethereum::TransactionAction::Call(to) => Some(to), - _ => None, - } - }, - |status| status.to, - ), - value: transaction.value, - gas_price: transaction.gas_price, - gas: transaction.gas_limit, - input: Bytes(transaction.clone().input), - creates: status.as_ref().and_then(|status| status.contract_address), - raw: Bytes(rlp::encode(&transaction).to_vec()), - public_key: pubkey.as_ref().map(H512::from), - chain_id: transaction.signature.chain_id().map(U64::from), - standard_v: U256::from(transaction.signature.standard_v()), - v: U256::from(transaction.signature.v()), - r: U256::from(transaction.signature.r().as_bytes()), - s: U256::from(transaction.signature.s().as_bytes()), - } + Some(transaction) } pub fn public_key(transaction: &EthereumTransaction) -> ruc::Result<[u8; 64]> { let mut sig = [0u8; 65]; let mut msg = [0u8; 32]; - sig[0..32].copy_from_slice(&transaction.signature.r()[..]); - sig[32..64].copy_from_slice(&transaction.signature.s()[..]); - sig[64] = transaction.signature.standard_v(); - msg.copy_from_slice( - &EthereumTransactionMessage::from(transaction.clone()).hash()[..], - ); - + match transaction { + EthereumTransaction::Legacy(t) => { + sig[0..32].copy_from_slice(&t.signature.r()[..]); + sig[32..64].copy_from_slice(&t.signature.s()[..]); + sig[64] = t.signature.standard_v(); + msg.copy_from_slice( + ðereum::LegacyTransactionMessage::from(t.clone()).hash()[..], + ); + } + EthereumTransaction::EIP1559(t) => { + sig[0..32].copy_from_slice(&t.r[..]); + sig[32..64].copy_from_slice(&t.s[..]); + sig[64] = t.odd_y_parity as u8; + msg.copy_from_slice( + ðereum::EIP1559TransactionMessage::from(t.clone()).hash()[..], + ); + } + _ => { + return Err(eg!("Transaction Type Error")); + } + } fp_types::crypto::secp256k1_ecdsa_recover(&sig, &msg) } @@ -1610,6 +1852,45 @@ fn native_block_id(number: Option) -> Option { } } +struct FeeDetails { + gas_price: Option, + max_fee_per_gas: Option, + max_priority_fee_per_gas: Option, +} + +fn fee_details( + request_gas_price: Option, + request_max_fee: Option, + request_priority: Option, +) -> Result { + match (request_gas_price, request_max_fee, request_priority) { + (gas_price, None, None) => { + // Legacy request, all default to gas price. + Ok(FeeDetails { + gas_price, + max_fee_per_gas: gas_price, + max_priority_fee_per_gas: gas_price, + }) + } + (_, max_fee, max_priority) => { + // eip-1559 + // Ensure `max_priority_fee_per_gas` is less or equal to `max_fee_per_gas`. + if let Some(max_priority) = max_priority { + let max_fee = max_fee.unwrap_or_default(); + if max_priority > max_fee { + return Err(internal_err( + "Invalid input: `max_priority_fee_per_gas` greater than `max_fee_per_gas`" + )); + } + } + Ok(FeeDetails { + gas_price: max_fee, + max_fee_per_gas: max_fee, + max_priority_fee_per_gas: max_priority, + }) + } + } +} fn dummy_block(height: u64, full: bool) -> Rich { let hash = if height == *EVM_FIRST_BLOCK_HEIGHT - 1 { H256([0; 32]) @@ -1626,6 +1907,9 @@ fn dummy_block(height: u64, full: bool) -> Rich { BlockTransactions::Hashes(vec![]) }; + let gas_price = + ::FeeCalculator::min_gas_price(height); + let inner = Block { hash: Some(hash), parent_hash, @@ -1661,6 +1945,7 @@ fn dummy_block(height: u64, full: bool) -> Rich { uncles: vec![], transactions, size: Some(U256::from(0x1_u32)), + base_fee_per_gas: Some(gas_price), }; Rich { diff --git a/src/components/contracts/rpc/src/eth_filter.rs b/src/components/contracts/rpc/src/eth_filter.rs index 18c71814d..7dce5b914 100644 --- a/src/components/contracts/rpc/src/eth_filter.rs +++ b/src/components/contracts/rpc/src/eth_filter.rs @@ -1,6 +1,6 @@ use crate::{filter_block_logs, internal_err}; use baseapp::BaseApp; -use ethereum::BlockV0 as EthereumBlock; +use ethereum::BlockV2 as EthereumBlock; use ethereum_types::{H256, U256}; use fp_evm::{BlockId, TransactionStatus}; use fp_rpc_core::types::{ diff --git a/src/components/contracts/rpc/src/eth_pubsub.rs b/src/components/contracts/rpc/src/eth_pubsub.rs index 21efe3166..ffa007b57 100644 --- a/src/components/contracts/rpc/src/eth_pubsub.rs +++ b/src/components/contracts/rpc/src/eth_pubsub.rs @@ -1,6 +1,6 @@ use baseapp::tm_events::{get_pendingtx, get_sync_status}; use baseapp::BaseApp; -use ethereum::{BlockV0 as EthereumBlock, ReceiptV0 as Receipt}; +use ethereum::{BlockV2 as EthereumBlock, ReceiptV0 as Receipt}; use ethereum_types::{H256, U256}; use fp_evm::BlockId; use fp_rpc_core::types::pubsub::PubSubSyncStatus; diff --git a/src/components/finutils/Cargo.toml b/src/components/finutils/Cargo.toml index 1782f2f98..83bf14733 100644 --- a/src/components/finutils/Cargo.toml +++ b/src/components/finutils/Cargo.toml @@ -22,7 +22,7 @@ serde = { version = "1.0.124", features = ["derive"] } sha2 = "0.10" tokio = "1.10.1" -wasm-bindgen = { version = "=0.2.73", features = ["serde-serialize"] } +wasm-bindgen = { version = "0.2.83", features = ["serde-serialize"] } getrandom = "0.2" noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } diff --git a/src/components/finutils/src/txn_builder/mod.rs b/src/components/finutils/src/txn_builder/mod.rs index 102cba254..d4afbd1e5 100644 --- a/src/components/finutils/src/txn_builder/mod.rs +++ b/src/components/finutils/src/txn_builder/mod.rs @@ -635,7 +635,6 @@ impl TransactionBuilder { /// * `enc_key` - XPublicKey of OwnerMemo encryption of receiver /// * `is_bar_transparent` - if transparent bar (ar) #[allow(clippy::too_many_arguments)] - pub fn add_operation_bar_to_abar( &mut self, seed: [u8; 32], diff --git a/src/components/wallet_mobile/Cargo.toml b/src/components/wallet_mobile/Cargo.toml index 53086d49a..d84459968 100644 --- a/src/components/wallet_mobile/Cargo.toml +++ b/src/components/wallet_mobile/Cargo.toml @@ -60,7 +60,7 @@ features = [ jni = "0.20" [target.'cfg(target_arch="wasm32")'.dependencies] -wasm-bindgen = { version = "=0.2.73", features = ["serde-serialize"] } +wasm-bindgen = { version = "0.2.83", features = ["serde-serialize"] } [target.'cfg(not(target_arch="wasm32"))'.dependencies] safer-ffi = "0.0.10" diff --git a/src/components/wasm/Cargo.toml b/src/components/wasm/Cargo.toml index fbd9de16d..970cb8c68 100644 --- a/src/components/wasm/Cargo.toml +++ b/src/components/wasm/Cargo.toml @@ -24,7 +24,7 @@ rand_chacha = "0.3" rand_core = { version = "0.6", default-features = false, features = ["alloc"] } serde = { version = "1.0.124", features = ["derive"] } serde_json = "1.0" -wasm-bindgen = { version = "=0.2.73", features = ["serde-serialize"] } +wasm-bindgen = { version = "0.2.83", features = ["serde-serialize"] } bs58 = "0.4" ring = "0.16.19" @@ -71,7 +71,7 @@ features = [ serde = "1.0.124" serde_json = "1.0.41" vergen = "=3.1.0" -wasm-bindgen = { version = "=0.2.73", features = ["serde-serialize"] } +wasm-bindgen = { version = "0.2.83", features = ["serde-serialize"] } [dev-dependencies] # Must enable the "js"-feature, diff --git a/src/libs/bitmap/src/lib.rs b/src/libs/bitmap/src/lib.rs index fbf2bed15..c3dbe68ca 100644 --- a/src/libs/bitmap/src/lib.rs +++ b/src/libs/bitmap/src/lib.rs @@ -566,7 +566,7 @@ fn count_byte(mask: usize) -> u8 { let mut result = 0; for i in 0..8 { - result += (mask & (1 << i) != 0) as u8; + result += u8::from(mask & (1 << i) != 0); } result diff --git a/src/libs/credentials/Cargo.toml b/src/libs/credentials/Cargo.toml index 8b1819d3a..021e14dad 100644 --- a/src/libs/credentials/Cargo.toml +++ b/src/libs/credentials/Cargo.toml @@ -11,6 +11,6 @@ rand_core = { version = "0.6", default-features = false, features = ["alloc"] } linear-map = {version = "1.2.0", features = ["serde_impl"] } serde = "1.0.124" serde_derive = "1.0" -wasm-bindgen = { version = "=0.2.73", features = ["serde-serialize"] } +wasm-bindgen = { version = "0.2.83", features = ["serde-serialize"] } noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } From 31fcd09fc52dca392b5e61fbb2cc2c3010557c45 Mon Sep 17 00:00:00 2001 From: harry Date: Fri, 6 Jan 2023 09:05:57 +0800 Subject: [PATCH 02/10] revert to no eip1559 --- src/components/config/src/abci/mod.rs | 3 - .../contracts/baseapp/src/extensions.rs | 10 +- src/components/contracts/baseapp/src/lib.rs | 36 +- .../contracts/modules/account/src/impls.rs | 10 - .../contracts/modules/account/src/lib.rs | 4 +- .../contracts/modules/ethereum/src/impls.rs | 110 +--- .../contracts/modules/ethereum/src/lib.rs | 81 +-- .../contracts/modules/evm/Cargo.toml | 1 - .../modules/evm/precompile/utils/Cargo.toml | 1 - .../contracts/modules/evm/src/impls.rs | 7 - .../contracts/modules/evm/src/lib.rs | 12 +- .../modules/evm/src/runtime/runner.rs | 93 +-- .../modules/evm/tests/evm_integration.rs | 2 - .../template/tests/template_integration.rs | 6 +- .../contracts/primitives/evm/src/lib.rs | 4 +- .../contracts/primitives/mocks/src/lib.rs | 6 +- .../contracts/primitives/rpc-core/Cargo.toml | 2 - .../primitives/rpc-core/src/types/block.rs | 2 - .../rpc-core/src/types/call_request.rs | 4 - .../primitives/rpc-core/src/types/mod.rs | 2 +- .../primitives/rpc-core/src/types/receipt.rs | 3 - .../rpc-core/src/types/transaction.rs | 68 +-- .../rpc-core/src/types/transaction_request.rs | 62 +- .../primitives/traits/src/account.rs | 11 +- .../contracts/primitives/traits/src/base.rs | 2 +- .../contracts/primitives/traits/src/evm.rs | 3 - .../primitives/types/src/actions/ethereum.rs | 2 +- .../primitives/types/src/actions/evm.rs | 6 - .../primitives/types/src/assemble.rs | 2 +- .../contracts/primitives/utils/Cargo.toml | 2 - .../contracts/primitives/wasm/Cargo.toml | 2 +- .../contracts/primitives/wasm/src/wasm.rs | 47 +- src/components/contracts/rpc/src/eth.rs | 573 +++++------------- .../contracts/rpc/src/eth_filter.rs | 2 +- .../contracts/rpc/src/eth_pubsub.rs | 2 +- src/components/finutils/Cargo.toml | 2 +- .../finutils/src/txn_builder/mod.rs | 1 + src/components/wallet_mobile/Cargo.toml | 2 +- src/components/wasm/Cargo.toml | 4 +- src/libs/bitmap/src/lib.rs | 2 +- src/libs/credentials/Cargo.toml | 2 +- 41 files changed, 290 insertions(+), 906 deletions(-) diff --git a/src/components/config/src/abci/mod.rs b/src/components/config/src/abci/mod.rs index f20193426..b97a41c6b 100644 --- a/src/components/config/src/abci/mod.rs +++ b/src/components/config/src/abci/mod.rs @@ -88,7 +88,6 @@ pub struct CheckPointConfig { // Fix the amount in the delegators that staking did not modify when it punished the validator. pub fix_delegators_am_height: u64, pub validators_limit_v2_height: u64, - pub enable_eip1559_height: u64, } impl CheckPointConfig { @@ -128,7 +127,6 @@ impl CheckPointConfig { proper_gas_set_height: 0, fix_delegators_am_height: 0, validators_limit_v2_height: 0, - enable_eip1559_height: 0, }; #[cfg(not(feature = "debug_env"))] let config = CheckPointConfig { @@ -158,7 +156,6 @@ impl CheckPointConfig { fix_undelegation_missing_reward_height: 3000000, fix_delegators_am_height: 30000000, validators_limit_v2_height: 30000000, - enable_eip1559_height: 40000000, }; let content = toml::to_string(&config).unwrap(); file.write_all(content.as_bytes()).unwrap(); diff --git a/src/components/contracts/baseapp/src/extensions.rs b/src/components/contracts/baseapp/src/extensions.rs index e75a9eaf9..d17977e40 100644 --- a/src/components/contracts/baseapp/src/extensions.rs +++ b/src/components/contracts/baseapp/src/extensions.rs @@ -4,7 +4,7 @@ use fp_core::{ context::Context, transaction::{ActionResult, SignedExtension}, }; -use fp_traits::{account::AccountAsset, evm::FeeCalculator}; +use fp_traits::account::{AccountAsset, FeeCalculator}; use fp_types::crypto::Address; use primitive_types::U256; use ruc::*; @@ -64,9 +64,7 @@ impl SignedExtension for CheckFee { type Pre = (Address, U256); fn validate(&self, ctx: &Context, who: &Self::AccountId) -> Result<()> { - let min_fee = ::FeeCalculator::min_gas_price( - ctx.header.height as u64, - ); + let min_fee = ::FeeCalculator::min_fee(); let tx_fee = match self.0 { None => min_fee, Some(fee) => { @@ -87,9 +85,7 @@ impl SignedExtension for CheckFee { } fn pre_execute(self, ctx: &Context, who: &Self::AccountId) -> Result { - let min_fee = ::FeeCalculator::min_gas_price( - ctx.header.height as u64, - ); + let min_fee = ::FeeCalculator::min_fee(); let tx_fee = match self.0 { None => min_fee, Some(fee) => { diff --git a/src/components/contracts/baseapp/src/lib.rs b/src/components/contracts/baseapp/src/lib.rs index 1f902f0b5..02de696a1 100644 --- a/src/components/contracts/baseapp/src/lib.rs +++ b/src/components/contracts/baseapp/src/lib.rs @@ -13,7 +13,7 @@ pub mod tm_events; use crate::modules::ModuleManager; use abci::Header; -use ethereum::BlockV2 as Block; +use ethereum::BlockV0 as Block; use evm_precompile::{self, FindoraPrecompiles}; use fin_db::{FinDB, RocksDB}; use fp_core::context::Context as Context2; @@ -25,11 +25,9 @@ use fp_core::{ }; use fp_evm::BlockId; use fp_traits::{ - account::AccountAsset, + account::{AccountAsset, FeeCalculator}, base::BaseProvider, - evm::{ - DecimalsMapping, EthereumAddressMapping, EthereumDecimalsMapping, - }, + evm::{DecimalsMapping, EthereumAddressMapping, EthereumDecimalsMapping}, }; use fp_types::{actions::xhub::NonConfidentialOutput, actions::Action, crypto::Address}; use lazy_static::lazy_static; @@ -56,23 +54,6 @@ const CHAIN_STATE_PATH: &str = "state.db"; const CHAIN_HISTORY_DATA_PATH: &str = "history.db"; const BLOCKS_IN_DAY: u64 = 4 * 60 * 24; -const INITIAL_BASE_FEE: u64 = 1000000000; -const ELASTICITY_MULTIPLIER: u64 = 2; -const BASE_FEE_MAX_CHANGE_DENOMINATOR: u64 = 8; - -#[inline(always)] -pub fn get_initial_base_fee() -> U256 { - U256::from(INITIAL_BASE_FEE) -} -#[inline(always)] -pub fn get_elasticity_multiplier() -> U256 { - U256::from(ELASTICITY_MULTIPLIER) -} -#[inline(always)] -pub fn get_base_fee_max_change_denominator() -> U256 { - U256::from(BASE_FEE_MAX_CHANGE_DENOMINATOR) -} - #[derive(Clone)] pub struct BaseApp { /// application name from abci.Info @@ -100,8 +81,17 @@ pub struct BaseApp { impl module_template::Config for BaseApp {} +pub struct StableTxFee; + +impl FeeCalculator for StableTxFee { + fn min_fee() -> U256 { + // TX_FEE_MIN + U256::from(1_0000_0000_0000_0000_u64) + } +} + impl module_account::Config for BaseApp { - type FeeCalculator = (); + type FeeCalculator = StableTxFee; } parameter_types! { diff --git a/src/components/contracts/modules/account/src/impls.rs b/src/components/contracts/modules/account/src/impls.rs index e3cbba4af..c0ff983cf 100644 --- a/src/components/contracts/modules/account/src/impls.rs +++ b/src/components/contracts/modules/account/src/impls.rs @@ -242,14 +242,4 @@ impl AccountAsset
for App { ) -> Result<()> { Allowances::insert(ctx.state.write().borrow_mut(), owner, spender, &amount) } - - fn income(ctx: &Context, who: &Address, value: U256) -> Result<()> { - if value.is_zero() { - return Ok(()); - } - - let mut sa = Self::account_of(ctx, who, None).c(d!("account does not exist"))?; - sa.balance = sa.balance.checked_add(value).c(d!("balance overflow"))?; - AccountStore::insert(ctx.state.write().borrow_mut(), who, &sa) - } } diff --git a/src/components/contracts/modules/account/src/lib.rs b/src/components/contracts/modules/account/src/lib.rs index 4192005c6..7429c47dc 100644 --- a/src/components/contracts/modules/account/src/lib.rs +++ b/src/components/contracts/modules/account/src/lib.rs @@ -12,8 +12,8 @@ mod tests; use abci::{RequestQuery, ResponseQuery}; use fp_core::{context::Context, module::AppModule}; use fp_traits::{ - account::AccountAsset, - evm::{DecimalsMapping, EthereumDecimalsMapping, FeeCalculator}, + account::{AccountAsset, FeeCalculator}, + evm::{DecimalsMapping, EthereumDecimalsMapping}, }; use fp_types::crypto::Address; use std::marker::PhantomData; diff --git a/src/components/contracts/modules/ethereum/src/impls.rs b/src/components/contracts/modules/ethereum/src/impls.rs index 5346e5193..61654416b 100644 --- a/src/components/contracts/modules/ethereum/src/impls.rs +++ b/src/components/contracts/modules/ethereum/src/impls.rs @@ -1,7 +1,10 @@ use crate::storage::*; use crate::{App, Config, ContractLog, TransactionExecuted}; use config::abci::global_cfg::CFG; -use ethereum::{BlockV2 as Block, ReceiptV0 as Receipt, TransactionV2 as Transaction}; +use ethereum::{ + BlockV0 as Block, LegacyTransactionMessage, ReceiptV0 as Receipt, + TransactionV0 as Transaction, +}; use ethereum_types::{Bloom, BloomInput, H160, H256, H64, U256}; use evm::{ExitFatal, ExitReason}; use fp_core::{ @@ -13,8 +16,10 @@ use fp_core::{ use fp_events::Event; use fp_evm::{BlockId, CallOrCreateInfo, Runner, TransactionStatus}; use fp_storage::{Borrow, BorrowMut}; -// use fp_types::crypto::secp256k1_ecdsa_recover; -use fp_types::{actions::evm as EvmAction, crypto::HA256}; +use fp_types::{ + actions::evm as EvmAction, + crypto::{secp256k1_ecdsa_recover, HA256}, +}; use fp_utils::{proposer_converter, timestamp_converter}; use ruc::*; use sha3::{Digest, Keccak256}; @@ -58,28 +63,14 @@ impl App { pub fn recover_signer(transaction: &Transaction) -> Option { let mut sig = [0u8; 65]; let mut msg = [0u8; 32]; - match transaction { - Transaction::Legacy(t) => { - sig[0..32].copy_from_slice(&t.signature.r()[..]); - sig[32..64].copy_from_slice(&t.signature.s()[..]); - sig[64] = t.signature.standard_v(); - msg.copy_from_slice( - ðereum::LegacyTransactionMessage::from(t.clone()).hash()[..], - ); - } - Transaction::EIP1559(t) => { - sig[0..32].copy_from_slice(&t.r[..]); - sig[32..64].copy_from_slice(&t.s[..]); - sig[64] = t.odd_y_parity as u8; - msg.copy_from_slice( - ðereum::EIP1559TransactionMessage::from(t.clone()).hash()[..], - ); - } - _ => { - return None; - } - } - let pubkey = fp_types::crypto::secp256k1_ecdsa_recover(&sig, &msg).ok()?; + sig[0..32].copy_from_slice(&transaction.signature.r()[..]); + sig[32..64].copy_from_slice(&transaction.signature.s()[..]); + sig[64] = transaction.signature.standard_v(); + msg.copy_from_slice( + &LegacyTransactionMessage::from(transaction.clone()).hash()[..], + ); + + let pubkey = secp256k1_ecdsa_recover(&sig, &msg).ok()?; Some(H160::from(H256::from_slice( Keccak256::digest(pubkey).as_slice(), ))) @@ -234,7 +225,8 @@ impl App { let source = Self::recover_signer_fast(ctx, &transaction) .ok_or_else(|| eg!("ExecuteTransaction: InvalidSignature"))?; - let transaction_hash = transaction.hash(); + let transaction_hash = + H256::from_slice(Keccak256::digest(&rlp::encode(&transaction)).as_slice()); let transaction_index = if just_check { 0 @@ -244,66 +236,22 @@ impl App { txns.len() as u32 }; - let ( - nonce, - gas_price, - gas_limit, - action, - value, - input, - _max_priority_fee_per_gas, - _max_fee_per_gas, - _chain_id, - _access_list, - ) = match &transaction { - Transaction::Legacy(transaction) => ( - transaction.nonce, - transaction.gas_price, - transaction.gas_limit, - transaction.action, - transaction.value, - transaction.input.clone(), - transaction.gas_price, - U256::from(0), - match transaction.signature.chain_id() { - Some(chain_id) => chain_id, - None => return Err(eg!("Must provide chainId")), - }, - vec![], - ), - Transaction::EIP1559(transaction) => ( - transaction.nonce, - transaction.max_fee_per_gas, - transaction.gas_limit, - transaction.action, - transaction.value, - transaction.input.clone(), - transaction.max_fee_per_gas, - transaction.max_priority_fee_per_gas, - transaction.chain_id, - transaction.access_list.clone(), - ), - _ => { - return Err(eg!("Unsupported Transaction Type")); - } - }; + let gas_limit = transaction.gas_limit; let execute_ret = Self::execute_transaction( ctx, source, - input, - value, - gas_limit, - Some(gas_price), - None, - None, - Some(nonce), - action, + transaction.input.clone(), + transaction.value, + transaction.gas_limit, + Some(transaction.gas_price), + Some(transaction.nonce), + transaction.action, ); if let Err(e) = execute_ret { let mut to = Default::default(); - if let ethereum::TransactionAction::Call(target) = action { + if let ethereum::TransactionAction::Call(target) = transaction.action { to = target; } events.push(Event::emit_event( @@ -462,8 +410,6 @@ impl App { value: U256, gas_limit: U256, gas_price: Option, - max_fee_per_gas: Option, - max_priority_fee_per_gas: Option, nonce: Option, action: ethereum::TransactionAction, ) -> Result<(Option, Option, CallOrCreateInfo)> { @@ -478,8 +424,6 @@ impl App { value, gas_limit: gas_limit.low_u64(), gas_price, - max_fee_per_gas, - max_priority_fee_per_gas, nonce, }, C::config(), @@ -496,8 +440,6 @@ impl App { value, gas_limit: gas_limit.low_u64(), gas_price, - max_fee_per_gas, - max_priority_fee_per_gas, nonce, }, C::config(), diff --git a/src/components/contracts/modules/ethereum/src/lib.rs b/src/components/contracts/modules/ethereum/src/lib.rs index de1c16f69..07c180354 100644 --- a/src/components/contracts/modules/ethereum/src/lib.rs +++ b/src/components/contracts/modules/ethereum/src/lib.rs @@ -5,7 +5,6 @@ mod basic; mod impls; use config::abci::global_cfg::CFG; -use ethereum::TransactionV2 as Transaction; use ethereum_types::{H160, H256, U256}; use evm::Config as EvmConfig; use fp_core::context::RunTxMode; @@ -55,7 +54,7 @@ pub trait Config { pub mod storage { use ethereum::{ - BlockV2 as Block, ReceiptV0 as Receipt, TransactionV2 as Transaction, + BlockV0 as Block, ReceiptV0 as Receipt, TransactionV0 as Transaction, }; use ethereum_types::U256; use fp_evm::TransactionStatus; @@ -177,92 +176,60 @@ impl ValidateUnsigned for App { fn validate_unsigned(ctx: &Context, call: &Self::Call) -> Result<()> { let Action::Transact(transaction) = call; - - let ( - nonce, - gas_price, - gas_limit, - value, - chain_id, - _max_fee_per_gas, - _max_priority_fee_per_gas, - _is_eip1559, - ) = match transaction { - Transaction::Legacy(t) => ( - t.nonce, - t.gas_price, - t.gas_limit, - t.value, - match t.signature.chain_id() { - Some(chain_id) => chain_id, - None => return Err(eg!("Must provide chainId")), - }, - U256::zero(), - U256::zero(), - false, - ), - Transaction::EIP1559(t) => ( - t.nonce, - U256::zero(), - t.gas_limit, - t.value, - t.chain_id, - t.max_fee_per_gas, - t.max_priority_fee_per_gas, - true, - ), - _ => { - return Err(eg!("Transaction Type Error")); + if let Some(chain_id) = transaction.signature.chain_id() { + if chain_id != C::ChainId::get() { + return Err(eg!(format!( + "InvalidChainId, got {}, but expected {}", + chain_id, + C::ChainId::get() + ))); } - }; - - if chain_id != C::ChainId::get() { - return Err(eg!(format!( - "InvalidChainId, got {}, but expected {}", - chain_id, - C::ChainId::get() - ))); + } else { + return Err(eg!("Must provide chainId".to_string())); } let origin = Self::recover_signer_fast(ctx, transaction) .ok_or_else(|| eg!("ExecuteTransaction: InvalidSignature"))?; // Same as go ethereum, Min gas limit is 21000. - if gas_limit < U256::from(21000) || gas_limit > C::BlockGasLimit::get() { + if transaction.gas_limit < U256::from(21000) + || transaction.gas_limit > C::BlockGasLimit::get() + { return Err(eg!(format!( "InvalidGasLimit: got {}, the gas limit must be in range [21000, {}]", - gas_limit, + transaction.gas_limit, C::BlockGasLimit::get() ))); } let min_gas_price = C::FeeCalculator::min_gas_price(ctx.header.height as u64); - if gas_price < min_gas_price { + if transaction.gas_price < min_gas_price { return Err(eg!(format!( "InvalidGasPrice: got {}, but the minimum gas price is {}", - gas_price, min_gas_price + transaction.gas_price, min_gas_price ))); } let account_id = C::AddressMapping::convert_to_account_id(origin); let account = C::AccountAsset::account_of(ctx, &account_id, None).unwrap_or_default(); + let nonce = account.nonce; + let balance = account.balance; - if nonce < account.nonce { + if transaction.nonce < nonce { return Err(eg!(format!( "InvalidNonce: origin: {:?}, got {}, but expected {}", - origin, nonce, account.nonce + origin, transaction.nonce, nonce ))); } - let fee = gas_price.saturating_mul(gas_limit); - let total_payment = value.saturating_add(fee); - - if account.balance < total_payment { + let fee = transaction.gas_price.saturating_mul(transaction.gas_limit); + let total_payment = transaction.value.saturating_add(fee); + if balance < total_payment { return Err(eg!(format!( "InsufficientBalance, origin: {:?}, actual balance {}, but expected payment {}", - origin, account.balance, total_payment + origin, balance, total_payment ))); } diff --git a/src/components/contracts/modules/evm/Cargo.toml b/src/components/contracts/modules/evm/Cargo.toml index 1b01e3e68..6bac465ee 100644 --- a/src/components/contracts/modules/evm/Cargo.toml +++ b/src/components/contracts/modules/evm/Cargo.toml @@ -16,7 +16,6 @@ evm-runtime = { version = "0.35.0", default-features = false } evm-gasometer = { version = "0.30.0", default-features = false } ethereum = { version = "0.12.0", default-features = false, features = ["with-serde"] } impl-trait-for-tuples = "0.2" -log = "0.4" tracing = "0.1" rlp = { version = "0.5", default-features = false } ruc = "1.0" diff --git a/src/components/contracts/modules/evm/precompile/utils/Cargo.toml b/src/components/contracts/modules/evm/precompile/utils/Cargo.toml index 8deb7e314..5a2091980 100644 --- a/src/components/contracts/modules/evm/precompile/utils/Cargo.toml +++ b/src/components/contracts/modules/evm/precompile/utils/Cargo.toml @@ -13,4 +13,3 @@ tracing = "0.1" num_enum = { version = "0.5.3", default-features = false } precompile-utils-macro = { path = "macro" } sha3 = { version = "0.10", default-features = false } -module-evm = { path = "../../../../modules/evm"} diff --git a/src/components/contracts/modules/evm/src/impls.rs b/src/components/contracts/modules/evm/src/impls.rs index 071d2a3d8..bf405846c 100644 --- a/src/components/contracts/modules/evm/src/impls.rs +++ b/src/components/contracts/modules/evm/src/impls.rs @@ -108,11 +108,4 @@ impl OnChargeEVMTransaction for App { C::AccountAsset::refund(ctx, &account_id, already_withdrawn)?; C::AccountAsset::burn(ctx, &account_id, corrected_fee) } - - fn pay_priority_fee(ctx: &Context, tip: U256) -> Result<()> { - let author = App::::find_proposer(ctx); - let account_id = C::AddressMapping::convert_to_account_id(author); - - C::AccountAsset::income(ctx, &account_id, tip) - } } diff --git a/src/components/contracts/modules/evm/src/lib.rs b/src/components/contracts/modules/evm/src/lib.rs index 23e11d9c0..3839482c3 100644 --- a/src/components/contracts/modules/evm/src/lib.rs +++ b/src/components/contracts/modules/evm/src/lib.rs @@ -33,7 +33,7 @@ use fp_evm::TransactionStatus; use evm::executor::stack::PrecompileSet as EvmPrecompileSet; use ethereum::{ - Log, ReceiptV0 as Receipt, TransactionAction, TransactionSignature, TransactionV2, + Log, ReceiptV0 as Receipt, TransactionAction, TransactionSignature, TransactionV0, }; use fp_types::{ @@ -110,7 +110,7 @@ impl App { _lowlevel: Vec, transaction_index: u32, transaction_hash: H256, - ) -> Result<(TransactionV2, TransactionStatus, Receipt)> { + ) -> Result<(TransactionV0, TransactionStatus, Receipt)> { let function = self.contracts.bridge.function("withdrawAsset").c(d!())?; let asset = Token::FixedBytes(Vec::from(_asset)); @@ -167,7 +167,7 @@ impl App { _lowlevel: Vec, transaction_index: u32, transaction_hash: H256, - ) -> Result<(TransactionV2, TransactionStatus, Receipt)> { + ) -> Result<(TransactionV0, TransactionStatus, Receipt)> { let function = self.contracts.bridge.function("withdrawFRA").c(d!())?; let from = Token::Bytes(from.noah_to_bytes()); @@ -251,13 +251,13 @@ impl App { from: H160, to: H160, logs: Vec, - ) -> (TransactionV2, TransactionStatus, Receipt) { + ) -> (TransactionV0, TransactionStatus, Receipt) { let signature_fake = H256([ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, ]); - let tx = TransactionV2::Legacy(ethereum::LegacyTransaction { + let tx = TransactionV0 { nonce: U256::zero(), gas_price, gas_limit, @@ -266,7 +266,7 @@ impl App { .unwrap(), input, action, - }); + }; let mut logs_bloom = Bloom::default(); Self::logs_bloom(&logs, &mut logs_bloom); diff --git a/src/components/contracts/modules/evm/src/runtime/runner.rs b/src/components/contracts/modules/evm/src/runtime/runner.rs index 0c45bad38..7525ac9b1 100644 --- a/src/components/contracts/modules/evm/src/runtime/runner.rs +++ b/src/components/contracts/modules/evm/src/runtime/runner.rs @@ -30,8 +30,7 @@ impl ActionRunner { source: H160, value: U256, gas_limit: u64, - max_fee_per_gas: Option, - max_priority_fee_per_gas: Option, + gas_price: Option, nonce: Option, config: &'config evm::Config, precompiles: &'precompiles C::PrecompilesType, @@ -47,43 +46,30 @@ impl ActionRunner { >, ) -> (ExitReason, R), { - let base_fee = C::FeeCalculator::min_gas_price(ctx.header.height as u64); + let min_gas_price = C::FeeCalculator::min_gas_price(ctx.header.height as u64); // Gas price check is skipped when performing a gas estimation. - let max_fee_per_gas = match max_fee_per_gas { - Some(max_fee_per_gas) => { - ensure!(max_fee_per_gas >= base_fee, "GasPriceTooLow"); - max_fee_per_gas + let gas_price = match gas_price { + Some(gas_price) => { + ensure!(gas_price >= min_gas_price, "GasPriceTooLow"); + gas_price } None => Default::default(), }; let vicinity = Vicinity { - gas_price: max_fee_per_gas, + gas_price, origin: source, }; let metadata = StackSubstateMetadata::new(gas_limit, config); - let state = FindoraStackState::::new(ctx, &vicinity, metadata); + let state = FindoraStackState::new(ctx, &vicinity, metadata); let mut executor = StackExecutor::new_with_precompiles(state, config, precompiles); - // After eip-1559 we make sure the account can pay both the evm execution and priority fees. - let max_base_fee = max_fee_per_gas + let total_fee = gas_price .checked_mul(U256::from(gas_limit)) .ok_or(eg!("FeeOverflow"))?; - let max_priority_fee = if let Some(max_priority_fee) = max_priority_fee_per_gas { - max_priority_fee - .checked_mul(U256::from(gas_limit)) - .ok_or(eg!("FeeOverflow"))? - } else { - U256::zero() - }; - - let total_fee = max_base_fee - .checked_add(max_priority_fee) - .ok_or(eg!("FeeOverflow"))?; - let total_payment = value.checked_add(total_fee).ok_or(eg!("PaymentOverflow"))?; let source_account = App::::account_basic(ctx, &source); @@ -97,6 +83,7 @@ impl ActionRunner { ) ); } + if !config.estimate { ensure!(source_account.balance >= total_payment, "BalanceLow"); @@ -108,60 +95,27 @@ impl ActionRunner { let (reason, retv) = f(&mut executor); let used_gas = U256::from(executor.used_gas()); - let (actual_fee, actual_priority_fee) = - if let Some(max_priority_fee) = max_priority_fee_per_gas { - let actual_priority_fee = max_priority_fee - .checked_mul(used_gas) - .ok_or(eg!("FeeOverflow"))?; - let actual_fee = executor - .fee(base_fee) - .checked_add(actual_priority_fee) - .unwrap_or_else(U256::max_value); - (actual_fee, Some(actual_priority_fee)) - } else { - (executor.fee(base_fee), None) - }; - tracing::trace!( + let actual_fee = executor.fee(gas_price); + tracing::debug!( target: "evm", - "Execution {:?} [source: {:?}, value: {}, gas_limit: {}, actual_fee: {}]", + "Execution {:?} [source: {:?}, value: {}, gas_price {}, gas_limit: {}, actual_fee: {}]", reason, source, value, + gas_price, gas_limit, actual_fee ); - // The difference between initially withdrawn and the actual cost is refunded. - // - // Considered the following request: - // +-----------+---------+--------------+ - // | Gas_limit | Max_Fee | Max_Priority | - // +-----------+---------+--------------+ - // | 20 | 10 | 6 | - // +-----------+---------+--------------+ - // - // And execution: - // +----------+----------+ - // | Gas_used | Base_Fee | - // +----------+----------+ - // | 5 | 2 | - // +----------+----------+ - // - // Initially withdrawn (10 + 6) * 20 = 320. - // Actual cost (2 + 6) * 5 = 40. - // Refunded 320 - 40 = 280. - // Tip 5 * 6 = 30. - // Burned 320 - (280 + 30) = 10. Which is equivalent to gas_used * base_fee. + if !config.estimate { + // Refund fees to the `source` account if deducted more before, App::::correct_and_deposit_fee(ctx, &source, actual_fee, total_fee)?; - if let Some(actual_priority_fee) = actual_priority_fee { - App::::pay_priority_fee(ctx, actual_priority_fee)?; - } } let state = executor.into_state(); for address in state.substate.deletes { - tracing::trace!( + tracing::debug!( target: "evm", "Deleting account at {:?}", address @@ -315,13 +269,13 @@ impl Runner for ActionRunner { fn call(ctx: &Context, args: Call, config: &evm::Config) -> Result { let precompiles = C::PrecompilesValue::get(ctx.clone()); let access_list = Vec::new(); + Self::execute( ctx, args.source, args.value, args.gas_limit, - args.max_fee_per_gas, - args.max_priority_fee_per_gas, + args.gas_price, args.nonce, config, &precompiles, @@ -341,13 +295,13 @@ impl Runner for ActionRunner { fn create(ctx: &Context, args: Create, config: &evm::Config) -> Result { let precompiles = C::PrecompilesValue::get(ctx.clone()); let access_list = Vec::new(); + Self::execute( ctx, args.source, args.value, args.gas_limit, - args.max_fee_per_gas, - args.max_priority_fee_per_gas, + args.gas_price, args.nonce, config, &precompiles, @@ -355,6 +309,7 @@ impl Runner for ActionRunner { let address = executor.create_address(evm::CreateScheme::Legacy { caller: args.source, }); + ( executor .transact_create( @@ -379,13 +334,13 @@ impl Runner for ActionRunner { let code_hash = H256::from_slice(Keccak256::digest(&args.init).as_slice()); let precompiles = C::PrecompilesValue::get(ctx.clone()); let access_list = Vec::new(); + Self::execute( ctx, args.source, args.value, args.gas_limit, - args.max_fee_per_gas, - args.max_priority_fee_per_gas, + args.gas_price, args.nonce, config, &precompiles, diff --git a/src/components/contracts/modules/evm/tests/evm_integration.rs b/src/components/contracts/modules/evm/tests/evm_integration.rs index 14ae5db8a..7f6163ce2 100644 --- a/src/components/contracts/modules/evm/tests/evm_integration.rs +++ b/src/components/contracts/modules/evm/tests/evm_integration.rs @@ -287,8 +287,6 @@ fn test_balance_of_with_eth_call(contract: ERC20, who: H160) -> U256 { value: U256::zero(), gas_limit: DEFAULT_GAS_LIMIT, gas_price: None, - max_fee_per_gas: None, - max_priority_fee_per_gas: None, nonce: None, }; diff --git a/src/components/contracts/modules/template/tests/template_integration.rs b/src/components/contracts/modules/template/tests/template_integration.rs index 34ff9615c..85c5f1587 100644 --- a/src/components/contracts/modules/template/tests/template_integration.rs +++ b/src/components/contracts/modules/template/tests/template_integration.rs @@ -3,7 +3,7 @@ //! Template module integration tests. use abci::*; use fp_mocks::*; -use fp_traits::{account::AccountAsset, evm::FeeCalculator}; +use fp_traits::account::{AccountAsset, FeeCalculator}; use fp_types::{actions::template::Action as TemplateAction, actions::Action, U256}; use fp_utils::tx::EvmRawTxWrapper; use module_template::ValueStore; @@ -149,9 +149,7 @@ fn test_abci_commit() { &ALICE_XFR.pub_key.into() ), U256::from(100_0000_0000_0000_0000_u64).saturating_sub( - ::FeeCalculator::min_gas_price( - BASE_APP.lock().unwrap().deliver_state.header.height as u64, - ) + ::FeeCalculator::min_fee() ) ); } diff --git a/src/components/contracts/primitives/evm/src/lib.rs b/src/components/contracts/primitives/evm/src/lib.rs index 62b37bda3..2b972ea60 100644 --- a/src/components/contracts/primitives/evm/src/lib.rs +++ b/src/components/contracts/primitives/evm/src/lib.rs @@ -4,9 +4,7 @@ use ethereum_types::{Bloom, H160, H256, U256}; use evm::ExitReason; use fp_core::context::Context; -use fp_types::actions::evm::{ - Call, Create, Create2, -}; +use fp_types::actions::evm::{Call, Create, Create2}; use ruc::*; use serde::{Deserialize, Serialize}; diff --git a/src/components/contracts/primitives/mocks/src/lib.rs b/src/components/contracts/primitives/mocks/src/lib.rs index 4eaed9676..f88cac008 100644 --- a/src/components/contracts/primitives/mocks/src/lib.rs +++ b/src/components/contracts/primitives/mocks/src/lib.rs @@ -7,7 +7,7 @@ pub use baseapp::{ }; pub use fp_types::{actions::Action, assemble::UncheckedTransaction}; -use ethereum::{TransactionAction, TransactionSignature, TransactionV2 as Transaction}; +use ethereum::{TransactionAction, TransactionSignature, TransactionV0 as Transaction}; use fp_traits::account::AccountAsset; use fp_traits::evm::{AddressMapping, EthereumAddressMapping}; use fp_types::crypto::{Address, MultiSignature}; @@ -148,7 +148,7 @@ impl UnsignedTransaction { ) .unwrap(); - Transaction::Legacy(ethereum::LegacyTransaction { + Transaction { nonce: self.nonce, gas_price: self.gas_price, gas_limit: self.gas_limit, @@ -156,6 +156,6 @@ impl UnsignedTransaction { value: self.value, input: self.input.clone(), signature: sig, - }) + } } } diff --git a/src/components/contracts/primitives/rpc-core/Cargo.toml b/src/components/contracts/primitives/rpc-core/Cargo.toml index 87ff9c686..81617b82f 100644 --- a/src/components/contracts/primitives/rpc-core/Cargo.toml +++ b/src/components/contracts/primitives/rpc-core/Cargo.toml @@ -9,8 +9,6 @@ description = "RPC traits of Ethereum." license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] -rlp = "0.5" -ethereum = { version = "0.12.0", default-features = false, features = ["with-serde"] } ethereum-types = "0.13.1" futures = "0.3.16" jsonrpc-core = { git = "https://github.com/FindoraNetwork/jsonrpc.git", package = "jsonrpc-core" } diff --git a/src/components/contracts/primitives/rpc-core/src/types/block.rs b/src/components/contracts/primitives/rpc-core/src/types/block.rs index 855ffa17f..5786136da 100644 --- a/src/components/contracts/primitives/rpc-core/src/types/block.rs +++ b/src/components/contracts/primitives/rpc-core/src/types/block.rs @@ -90,8 +90,6 @@ pub struct Block { pub transactions: BlockTransactions, /// Size in bytes pub size: Option, - /// Base Fee for post-EIP1559 blocks. - pub base_fee_per_gas: Option, } /// Block header representation. diff --git a/src/components/contracts/primitives/rpc-core/src/types/call_request.rs b/src/components/contracts/primitives/rpc-core/src/types/call_request.rs index 2e965b9c9..0451dbaf6 100644 --- a/src/components/contracts/primitives/rpc-core/src/types/call_request.rs +++ b/src/components/contracts/primitives/rpc-core/src/types/call_request.rs @@ -31,10 +31,6 @@ pub struct CallRequest { pub to: Option, /// Gas Price pub gas_price: Option, - /// EIP-1559 Max base fee the caller is willing to pay - pub max_fee_per_gas: Option, - /// EIP-1559 Priority fee the caller is paying to the block author - pub max_priority_fee_per_gas: Option, /// Gas pub gas: Option, /// Value diff --git a/src/components/contracts/primitives/rpc-core/src/types/mod.rs b/src/components/contracts/primitives/rpc-core/src/types/mod.rs index 422f78580..daa204156 100644 --- a/src/components/contracts/primitives/rpc-core/src/types/mod.rs +++ b/src/components/contracts/primitives/rpc-core/src/types/mod.rs @@ -56,5 +56,5 @@ pub use self::transaction::{ LocalTransactionStatus, PendingTransaction, PendingTransactions, RichRawTransaction, Transaction, }; -pub use self::transaction_request::{TransactionMessage, TransactionRequest}; +pub use self::transaction_request::TransactionRequest; pub use self::work::Work; diff --git a/src/components/contracts/primitives/rpc-core/src/types/receipt.rs b/src/components/contracts/primitives/rpc-core/src/types/receipt.rs index 846609176..5d1ed929e 100644 --- a/src/components/contracts/primitives/rpc-core/src/types/receipt.rs +++ b/src/components/contracts/primitives/rpc-core/src/types/receipt.rs @@ -54,7 +54,4 @@ pub struct Receipt { // NOTE(niklasad1): Unknown after EIP98 rules, if it's missing then skip serializing it #[serde(skip_serializing_if = "Option::is_none", rename = "status")] pub status_code: Option, - - /// Effective gas price. Pre-eip1559 this is just the gasprice. Post-eip1559 this is base fee + priority fee. - pub effective_gas_price: U256, } diff --git a/src/components/contracts/primitives/rpc-core/src/types/transaction.rs b/src/components/contracts/primitives/rpc-core/src/types/transaction.rs index d57e20f55..6d767f40c 100644 --- a/src/components/contracts/primitives/rpc-core/src/types/transaction.rs +++ b/src/components/contracts/primitives/rpc-core/src/types/transaction.rs @@ -17,7 +17,6 @@ // along with this program. If not, see . use crate::types::Bytes; -use ethereum::{AccessListItem, TransactionV2}; use ethereum_types::{H160, H256, H512, U256, U64}; use serde::ser::SerializeStruct; use serde::{Serialize, Serializer}; @@ -47,11 +46,7 @@ pub struct Transaction { /// Transfered value pub value: U256, /// Gas Price - pub gas_price: Option, - /// eip1559. Max BaseFeePerGas the user is willing to pay. - pub max_fee_per_gas: Option, - /// eip1559.The miner's tip. - pub max_priority_fee_per_gas: Option, + pub gas_price: U256, /// Gas pub gas: U256, /// Data @@ -72,67 +67,6 @@ pub struct Transaction { pub r: U256, /// The S field of the signature. pub s: U256, - /// eip1559. Pre-pay to warm storage access. - pub access_list: Option>, -} - -impl From for Transaction { - fn from(transaction: TransactionV2) -> Self { - let serialized = rlp::encode(&transaction); - let hash = transaction.hash(); - let raw = Bytes(serialized.to_vec()); - match transaction { - TransactionV2::Legacy(t) => Transaction { - hash, - nonce: t.nonce, - block_hash: None, - block_number: None, - transaction_index: None, - from: H160::default(), - to: None, - value: t.value, - gas_price: Some(t.gas_price), - max_fee_per_gas: Some(t.gas_price), - max_priority_fee_per_gas: Some(t.gas_price), - gas: t.gas_limit, - input: Bytes(t.clone().input), - creates: None, - raw, - public_key: None, - chain_id: t.signature.chain_id().map(U64::from), - standard_v: U256::from(t.signature.standard_v()), - v: U256::from(t.signature.v()), - r: U256::from(t.signature.r().as_bytes()), - s: U256::from(t.signature.s().as_bytes()), - access_list: None, - }, - TransactionV2::EIP1559(t) => Transaction { - hash, - nonce: t.nonce, - block_hash: None, - block_number: None, - transaction_index: None, - from: H160::default(), - to: None, - value: t.value, - gas_price: None, - max_fee_per_gas: Some(t.max_fee_per_gas), - max_priority_fee_per_gas: Some(t.max_priority_fee_per_gas), - gas: t.gas_limit, - input: Bytes(t.clone().input), - creates: None, - raw, - public_key: None, - chain_id: Some(U64::from(t.chain_id)), - standard_v: U256::from(t.odd_y_parity as u8), - v: U256::from(t.odd_y_parity as u8), - r: U256::from(t.r.as_bytes()), - s: U256::from(t.s.as_bytes()), - access_list: Some(t.access_list), - }, - _ => Transaction::default(), - } - } } /// Local Transaction Status diff --git a/src/components/contracts/primitives/rpc-core/src/types/transaction_request.rs b/src/components/contracts/primitives/rpc-core/src/types/transaction_request.rs index b4099b43f..bbddf8d5f 100644 --- a/src/components/contracts/primitives/rpc-core/src/types/transaction_request.rs +++ b/src/components/contracts/primitives/rpc-core/src/types/transaction_request.rs @@ -22,15 +22,8 @@ use crate::types::Bytes; use ethereum_types::{H160, U256}; use serde::{Deserialize, Serialize}; -use ethereum::{AccessListItem, EIP1559TransactionMessage, LegacyTransactionMessage}; - -pub enum TransactionMessage { - Legacy(LegacyTransactionMessage), - EIP1559(EIP1559TransactionMessage), -} - /// Transaction request coming from RPC -#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Serialize, Deserialize)] #[serde(deny_unknown_fields)] #[serde(rename_all = "camelCase")] pub struct TransactionRequest { @@ -40,10 +33,6 @@ pub struct TransactionRequest { pub to: Option, /// Gas Price pub gas_price: Option, - /// Max BaseFeePerGas the user is willing to pay. - pub max_fee_per_gas: Option, - /// The miner's tip. - pub max_priority_fee_per_gas: Option, /// Gas pub gas: Option, /// Value of transaction in wei @@ -52,53 +41,4 @@ pub struct TransactionRequest { pub data: Option, /// Transaction's nonce pub nonce: Option, - /// Pre-pay to warm storage access. - pub access_list: Option>, -} - -impl From for Option { - fn from(val: TransactionRequest) -> Option { - match (val.gas_price, val.max_fee_per_gas, val.access_list.clone()) { - // Legacy - (Some(_), None, None) => { - Some(TransactionMessage::Legacy(LegacyTransactionMessage { - nonce: U256::zero(), - gas_price: val.gas_price.unwrap_or_default(), - gas_limit: val.gas.unwrap_or_default(), - value: val.value.unwrap_or(U256::zero()), - input: val.data.map(|s| s.into_vec()).unwrap_or_default(), - action: match val.to { - Some(to) => ethereum::TransactionAction::Call(to), - None => ethereum::TransactionAction::Create, - }, - chain_id: None, - })) - } - // EIP1559 - (None, Some(_), _) | (None, None, None) => { - // Empty fields fall back to the canonical transaction schema. - Some(TransactionMessage::EIP1559(EIP1559TransactionMessage { - nonce: U256::zero(), - max_fee_per_gas: val.max_fee_per_gas.unwrap_or_default(), - max_priority_fee_per_gas: val - .max_priority_fee_per_gas - .unwrap_or_else(|| U256::from(0)), - gas_limit: val.gas.unwrap_or_default(), - value: val.value.unwrap_or(U256::zero()), - input: val.data.map(|s| s.into_vec()).unwrap_or_default(), - action: match val.to { - Some(to) => ethereum::TransactionAction::Call(to), - None => ethereum::TransactionAction::Create, - }, - chain_id: 0, - access_list: val - .access_list - .unwrap_or_default() - .into_iter() - .collect(), - })) - } - _ => None, - } - } } diff --git a/src/components/contracts/primitives/traits/src/account.rs b/src/components/contracts/primitives/traits/src/account.rs index 2397b0e1d..65bb14fd1 100644 --- a/src/components/contracts/primitives/traits/src/account.rs +++ b/src/components/contracts/primitives/traits/src/account.rs @@ -56,6 +56,15 @@ pub trait AccountAsset
{ spender: &Address, amount: U256, ) -> Result<()>; +} + +/// Outputs the current transaction fee. +pub trait FeeCalculator { + fn min_fee() -> U256; +} - fn income(ctx: &Context, who: &Address, value: U256) -> Result<()>; +impl FeeCalculator for () { + fn min_fee() -> U256 { + U256::zero() + } } diff --git a/src/components/contracts/primitives/traits/src/base.rs b/src/components/contracts/primitives/traits/src/base.rs index 1f11400ab..b25b35e35 100644 --- a/src/components/contracts/primitives/traits/src/base.rs +++ b/src/components/contracts/primitives/traits/src/base.rs @@ -1,4 +1,4 @@ -use ethereum::{BlockV2 as Block, ReceiptV0 as Receipt}; +use ethereum::{BlockV0 as Block, ReceiptV0 as Receipt}; use fp_core::account::SmartAccount; use fp_evm::BlockId; use fp_types::crypto::Address; diff --git a/src/components/contracts/primitives/traits/src/evm.rs b/src/components/contracts/primitives/traits/src/evm.rs index 4260c8991..7e6d000fd 100644 --- a/src/components/contracts/primitives/traits/src/evm.rs +++ b/src/components/contracts/primitives/traits/src/evm.rs @@ -81,7 +81,4 @@ pub trait OnChargeEVMTransaction { corrected_fee: U256, already_withdrawn: U256, ) -> Result<()>; - - /// Introduced in EIP1559 to handle the priority tip payment to the block Author. - fn pay_priority_fee(ctx: &Context, tip: U256) -> Result<()>; } diff --git a/src/components/contracts/primitives/types/src/actions/ethereum.rs b/src/components/contracts/primitives/types/src/actions/ethereum.rs index 4e5ab9fc8..5d2403a08 100644 --- a/src/components/contracts/primitives/types/src/actions/ethereum.rs +++ b/src/components/contracts/primitives/types/src/actions/ethereum.rs @@ -1,4 +1,4 @@ -use ethereum::TransactionV2 as Transaction; +use ethereum::TransactionV0 as Transaction; use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] diff --git a/src/components/contracts/primitives/types/src/actions/evm.rs b/src/components/contracts/primitives/types/src/actions/evm.rs index 39f2e6207..378d06a6d 100644 --- a/src/components/contracts/primitives/types/src/actions/evm.rs +++ b/src/components/contracts/primitives/types/src/actions/evm.rs @@ -16,8 +16,6 @@ pub struct Call { pub value: U256, pub gas_limit: u64, pub gas_price: Option, - pub max_fee_per_gas: Option, - pub max_priority_fee_per_gas: Option, pub nonce: Option, } @@ -28,8 +26,6 @@ pub struct Create { pub value: U256, pub gas_limit: u64, pub gas_price: Option, - pub max_fee_per_gas: Option, - pub max_priority_fee_per_gas: Option, pub nonce: Option, } @@ -41,7 +37,5 @@ pub struct Create2 { pub value: U256, pub gas_limit: u64, pub gas_price: Option, - pub max_fee_per_gas: Option, - pub max_priority_fee_per_gas: Option, pub nonce: Option, } diff --git a/src/components/contracts/primitives/types/src/assemble.rs b/src/components/contracts/primitives/types/src/assemble.rs index 3ea03b3e2..41cdb5a16 100644 --- a/src/components/contracts/primitives/types/src/assemble.rs +++ b/src/components/contracts/primitives/types/src/assemble.rs @@ -2,7 +2,7 @@ use crate::actions::ethereum::Action as EtherAction; use crate::actions::Action; use crate::crypto::{Address, Signature}; use crate::transaction; -use ethereum::TransactionV2 as Transaction; +use ethereum::TransactionV0 as Transaction; use primitive_types::U256; use ruc::*; use serde::{Deserialize, Serialize}; diff --git a/src/components/contracts/primitives/utils/Cargo.toml b/src/components/contracts/primitives/utils/Cargo.toml index 8ad50470c..672f13389 100644 --- a/src/components/contracts/primitives/utils/Cargo.toml +++ b/src/components/contracts/primitives/utils/Cargo.toml @@ -9,8 +9,6 @@ description = "Findora Primitive utility functions" readme = "README.md" [dependencies] -ethereum = { version = "0.12.0", default-features = false, features = ["with-serde"] } -ethereum-types = { version = "0.13.1", default-features = false } futures = "0.3.16" base64 = "0.13" bip0039 = "0.8.0" diff --git a/src/components/contracts/primitives/wasm/Cargo.toml b/src/components/contracts/primitives/wasm/Cargo.toml index e4318191c..7a35e137b 100644 --- a/src/components/contracts/primitives/wasm/Cargo.toml +++ b/src/components/contracts/primitives/wasm/Cargo.toml @@ -22,7 +22,7 @@ rlp = "0.5" ruc = "1.0" sha3 = "0.10" serde_json = "1.0" -wasm-bindgen = { version = "0.2.83", features = ["serde-serialize"] } +wasm-bindgen = { version = "=0.2.73", features = ["serde-serialize"] } # Must enable the "js"-feature, # OR the compiling will fail. diff --git a/src/components/contracts/primitives/wasm/src/wasm.rs b/src/components/contracts/primitives/wasm/src/wasm.rs index 846f97c04..f587e244c 100644 --- a/src/components/contracts/primitives/wasm/src/wasm.rs +++ b/src/components/contracts/primitives/wasm/src/wasm.rs @@ -1,11 +1,12 @@ #![allow(clippy::unused_unit)] use core::fmt::Display; -use ethereum::TransactionV2 as Transaction; +use ethereum::{LegacyTransactionMessage, TransactionV0 as Transaction}; use ethereum_types::{H160, H256}; use fp_types::{ actions::{ethereum::Action as EthAction, Action}, assemble::UncheckedTransaction, + crypto::secp256k1_ecdsa_recover, }; use fp_utils::tx::EvmRawTxWrapper; use ruc::{d, err::RucResult}; @@ -21,28 +22,12 @@ pub(crate) fn error_to_jsvalue(e: T) -> JsValue { pub fn recover_signer(transaction: &Transaction) -> Option { let mut sig = [0u8; 65]; let mut msg = [0u8; 32]; - match transaction { - Transaction::Legacy(t) => { - sig[0..32].copy_from_slice(&t.signature.r()[..]); - sig[32..64].copy_from_slice(&t.signature.s()[..]); - sig[64] = t.signature.standard_v(); - msg.copy_from_slice( - ðereum::LegacyTransactionMessage::from(t.clone()).hash()[..], - ); - } - Transaction::EIP1559(t) => { - sig[0..32].copy_from_slice(&t.r[..]); - sig[32..64].copy_from_slice(&t.s[..]); - sig[64] = t.odd_y_parity as u8; - msg.copy_from_slice( - ðereum::EIP1559TransactionMessage::from(t.clone()).hash()[..], - ); - } - _ => { - return None; - } - } - let pubkey = fp_types::crypto::secp256k1_ecdsa_recover(&sig, &msg).ok()?; + sig[0..32].copy_from_slice(&transaction.signature.r()[..]); + sig[32..64].copy_from_slice(&transaction.signature.s()[..]); + sig[64] = transaction.signature.standard_v(); + msg.copy_from_slice(&LegacyTransactionMessage::from(transaction.clone()).hash()[..]); + + let pubkey = secp256k1_ecdsa_recover(&sig, &msg).ok()?; Some(H160::from(H256::from_slice( Keccak256::digest(pubkey).as_slice(), ))) @@ -92,19 +77,20 @@ pub fn evm_tx_hash(raw_tx: String) -> Result { #[allow(missing_docs)] mod test { use super::*; - use fp_types::actions::{ethereum::Action as EthAction, Action}; + use fp_types::actions::Action; #[test] fn recover_signer_works() { - let raw_tx = String::from("ZXZtOnsiRXRoZXJldW0iOnsiVHJhbnNhY3QiOnsiRUlQMTU1OSI6eyJjaGFpbl9pZCI6MjE1Miwibm9uY2UiOiIweDEiLCJtYXhfcHJpb3JpdHlfZmVlX3Blcl9nYXMiOiIweDI3MTAiLCJtYXhfZmVlX3Blcl9nYXMiOiIweDI3MTAiLCJnYXNfbGltaXQiOiIweDI3MTAiLCJhY3Rpb24iOnsiQ2FsbCI6IjB4MmFkMzI4NDZjNmRkMmZmZDNlZGFkYmU1MWNkNWFlMDRhYTVlNTc1ZSJ9LCJ2YWx1ZSI6IjB4MjcxMCIsImlucHV0IjpbXSwiYWNjZXNzX2xpc3QiOltdLCJvZGRfeV9wYXJpdHkiOmZhbHNlLCJyIjoiMHhmOGFlZjdmODA1M2Q4OWZlZTM5NTBjNGQ3MDIwODBiZjNhODA3MmJlZDVkODRhM2FmMTlhMzYwMDgxYjYzNmEyIiwicyI6IjB4Mjk2Mjk5YThmMjQzMGI4NmZkM2ViOTc2ZWFiYzczMGFjMWNmYmJiZTM2ZWI2OWVhZTMzOGNmZjMzYzRhOThjMSJ9fX19"); + let raw_tx = String::from("ZXZtOnsic2lnbmF0dXJlIjpudWxsLCJmdW5jdGlvbiI6eyJFdGhlcmV1bSI6eyJUcmFuc2FjdCI6eyJub25jZSI6IjB4MSIsImdhc19wcmljZSI6IjB4MTc0ODc2ZTgwMCIsImdhc19saW1pdCI6IjB4NTIwOCIsImFjdGlvbiI6eyJDYWxsIjoiMHgyYWQzMjg0NmM2ZGQyZmZkM2VkYWRiZTUxY2Q1YWUwNGFhNWU1NzVlIn0sInZhbHVlIjoiMHg1NmJjNzVlMmQ2MzEwMDAwMCIsImlucHV0IjpbXSwic2lnbmF0dXJlIjp7InYiOjEwODIsInIiOiIweGY4YWVmN2Y4MDUzZDg5ZmVlMzk1MGM0ZDcwMjA4MGJmM2E4MDcyYmVkNWQ4NGEzYWYxOWEzNjAwODFiNjM2YTIiLCJzIjoiMHgyOTYyOTlhOGYyNDMwYjg2ZmQzZWI5NzZlYWJjNzMwYWMxY2ZiYmJlMzZlYjY5ZWFlMzM4Y2ZmMzNjNGE5OGMxIn19fX19"); let tx_bytes = base64::decode_config(raw_tx, base64::URL_SAFE).unwrap(); let evm_tx = EvmRawTxWrapper::unwrap(&tx_bytes).unwrap(); - let action: Action = serde_json::from_slice(evm_tx).unwrap(); - if let Action::Ethereum(EthAction::Transact(tx)) = action { + let unchecked_tx: UncheckedTransaction<()> = + serde_json::from_slice(evm_tx).unwrap(); + if let Action::Ethereum(EthAction::Transact(tx)) = unchecked_tx.function { let signer = recover_signer(&tx).unwrap(); assert_eq!( format!("{:?}", signer), - "0x7bc371bb41545d62117591e5051be3d2c6296f3e" + "0xa5225cbee5052100ec2d2d94aa6d258558073757" ); } else { panic!() @@ -112,9 +98,8 @@ mod test { } #[test] - // LegacyTransaction fn evm_tx_hash_works() { - let raw_tx = String::from("eyJzaWduYXR1cmUiOm51bGwsImZ1bmN0aW9uIjp7IkV0aGVyZXVtIjp7IlRyYW5zYWN0Ijp7IkxlZ2FjeSI6eyJub25jZSI6IjB4MCIsImdhc19wcmljZSI6IjB4MjU0MGJlNDAwIiwiZ2FzX2xpbWl0IjoiMHgxMDAwMDAiLCJhY3Rpb24iOnsiQ2FsbCI6IjB4MzMyNWE3ODQyNWYxN2E3ZTQ4N2ViNTY2NmIyYmZkOTNhYmIwNmM3MCJ9LCJ2YWx1ZSI6IjB4YSIsImlucHV0IjpbXSwic2lnbmF0dXJlIjp7InYiOjQzNDAsInIiOiIweDZiMjBjNzIzNTEzOTk4ZThmYTQ4NWM1MmI4ZjlhZTRmZDdiMWUwYmQwZGZiNzk4NTIzMThiMGMxMDBlOTFmNWUiLCJzIjoiMHg0ZDRjOGMxZjJlMTdjMDJjNGE4OTZlMjYyMTI3YjhiZDZlYmZkNWY1YTc1NWEzZTkyMjBjZmM2OGI4YzY5ZDVkIn19fX19fQ=="); + let raw_tx = String::from("eyJzaWduYXR1cmUiOm51bGwsImZ1bmN0aW9uIjp7IkV0aGVyZXVtIjp7IlRyYW5zYWN0Ijp7Im5vbmNlIjoiMHg5IiwiZ2FzX3ByaWNlIjoiMHhlOGQ0YTUxMDAwIiwiZ2FzX2xpbWl0IjoiMHg1MjA4IiwiYWN0aW9uIjp7IkNhbGwiOiIweGE1MjI1Y2JlZTUwNTIxMDBlYzJkMmQ5NGFhNmQyNTg1NTgwNzM3NTcifSwidmFsdWUiOiIweDk4YTdkOWI4MzE0YzAwMDAiLCJpbnB1dCI6W10sInNpZ25hdHVyZSI6eyJ2IjoxMDgyLCJyIjoiMHg4MDBjZjQ5ZTAzMmJhYzY4MjY3MzdhZGJhZDEzN2Y0MTk5OTRjNjgxZWE1ZDUyYjliMGJhZDJmNDAyYjMwMTI0IiwicyI6IjB4Mjk1Mjc3ZWY2NTYzNDAwY2VkNjFiODhkM2ZiNGM3YjMyY2NkNTcwYThiOWJiOGNiYmUyNTkyMTRhYjdkZTI1YSJ9fX19fQ=="); let tx_bytes = base64::decode_config(raw_tx, base64::URL_SAFE).unwrap(); let unchecked_tx: UncheckedTransaction<()> = serde_json::from_slice(tx_bytes.as_slice()).unwrap(); @@ -122,7 +107,7 @@ mod test { let hash = H256::from_slice(Keccak256::digest(&rlp::encode(&tx)).as_slice()); assert_eq!( format!("{:?}", hash), - "0x83901d025accca27ee53fdf1ee354f4437418731e0995ee031beb99499405d26" + "0x0eeb0ff455b1b57b821634cf853e7247e584a675610f13097cc49c2022505df3" ); } else { panic!() diff --git a/src/components/contracts/rpc/src/eth.rs b/src/components/contracts/rpc/src/eth.rs index a4781b3c2..5f572cb1b 100644 --- a/src/components/contracts/rpc/src/eth.rs +++ b/src/components/contracts/rpc/src/eth.rs @@ -7,17 +7,16 @@ use crate::{error_on_execution_failure, internal_err}; use baseapp::{extensions::SignedExtra, BaseApp}; use config::abci::global_cfg::CFG; use ethereum::{ - BlockV2 as EthereumBlock, - // LegacyTransactionMessage as EthereumTransactionMessage, - TransactionV2 as EthereumTransaction, + BlockV0 as EthereumBlock, LegacyTransactionMessage as EthereumTransactionMessage, + TransactionV0 as EthereumTransaction, }; use ethereum_types::{BigEndianHash, Bloom, H160, H256, H512, H64, U256, U64}; use evm::{ExitError, ExitReason}; use fp_evm::{BlockId, Runner, TransactionStatus}; use fp_rpc_core::types::{ Block, BlockNumber, BlockTransactions, Bytes, CallRequest, Filter, FilteredParams, - Index, Log, Receipt, Rich, RichBlock, SyncStatus, Transaction, TransactionMessage, - TransactionRequest, Work, + Index, Log, Receipt, Rich, RichBlock, SyncStatus, Transaction, TransactionRequest, + Work, }; use fp_rpc_core::EthApi; use fp_traits::{ @@ -180,6 +179,28 @@ impl EthApi for EthApiImpl { Ok(Some(::ChainId::get().into())) } + // let curr_height = match self.block_number() { + // Ok(h) => h.as_u64(), + // Err(e) => return Box::pin(future::err(e)), + // }; + + // let message = EthereumTransactionMessage { + // nonce, + // gas_price: request.gas_price.unwrap_or_else(|| { + // ::FeeCalculator::min_gas_price( + // curr_height, + // ) + // }), + // gas_limit: request.gas.unwrap_or_else(U256::max_value), + // value: request.value.unwrap_or_else(U256::zero), + // input: request.data.map(|s| s.into_vec()).unwrap_or_default(), + // action: match request.to { + // Some(to) => ethereum::TransactionAction::Call(to), + // None => ethereum::TransactionAction::Create, + // }, + // chain_id: chain_id.map(|s| s.as_u64()), + // }; + fn accounts(&self) -> Result> { self.accounts_sync() } @@ -235,63 +256,30 @@ impl EthApi for EthApiImpl { }; let chain_id = match self.chain_id() { - Ok(Some(chain_id)) => chain_id.as_u64(), - Ok(None) => { - return Box::pin(future::err(internal_err("chain id not available"))) - } + Ok(chain_id) => chain_id, Err(e) => return Box::pin(future::err(e)), }; - // let hash = self.client.info().best_hash; let curr_height = match self.block_number() { Ok(h) => h.as_u64(), Err(e) => return Box::pin(future::err(e)), }; - let gas_price = request.gas_price.unwrap_or_else(|| { - ::FeeCalculator::min_gas_price(curr_height) - }); - let block = self.account_base_app.read().current_block(None); - let gas_limit = match request.gas { - Some(gas_limit) => gas_limit, - None => { - if let Some(block) = block { - block.header.gas_limit - } else { - ::BlockGasLimit::get() - } - } - }; - - let max_fee_per_gas = request.max_fee_per_gas; - - let message: Option = request.into(); - let message = match message { - Some(TransactionMessage::Legacy(mut m)) => { - m.nonce = nonce; - m.chain_id = Some(chain_id); - m.gas_limit = gas_limit; - m.gas_price = gas_price; - TransactionMessage::Legacy(m) - } - Some(TransactionMessage::EIP1559(mut m)) => { - if CFG.checkpoint.enable_eip1559_height > curr_height { - return Box::pin(future::err(internal_err(format!( - "eip1559 not enabled at height: {:?}", - curr_height - )))); - } - m.nonce = nonce; - m.chain_id = chain_id; - m.gas_limit = gas_limit; - if max_fee_per_gas.is_none() { - m.max_fee_per_gas = self.gas_price().unwrap_or_default(); - } - TransactionMessage::EIP1559(m) - } - _ => { - return Box::pin(future::err(internal_err("Transaction Type Error"))); - } + let message = EthereumTransactionMessage { + nonce, + gas_price: request.gas_price.unwrap_or_else(|| { + ::FeeCalculator::min_gas_price( + curr_height, + ) + }), + gas_limit: request.gas.unwrap_or_else(U256::max_value), + value: request.value.unwrap_or_else(U256::zero), + input: request.data.map(|s| s.into_vec()).unwrap_or_default(), + action: match request.to { + Some(to) => ethereum::TransactionAction::Call(to), + None => ethereum::TransactionAction::Create, + }, + chain_id: chain_id.map(|s| s.as_u64()), }; let mut transaction = None; @@ -313,8 +301,8 @@ impl EthApi for EthApiImpl { return Box::pin(future::err(internal_err("no signer available"))); } }; - let transaction_hash = transaction.hash(); - + let transaction_hash = + H256::from_slice(Keccak256::digest(&rlp::encode(&transaction)).as_slice()); let function = actions::Action::Ethereum(actions::ethereum::Action::Transact(transaction)); let txn = serde_json::to_vec( @@ -364,28 +352,12 @@ impl EthApi for EthApiImpl { from, to, gas_price, - max_fee_per_gas, - max_priority_fee_per_gas, gas, value, data, nonce, } = request; - let _is_eip1559 = max_fee_per_gas.is_some() - && max_priority_fee_per_gas.is_some() - && max_fee_per_gas.unwrap() > U256::from(0) - && max_priority_fee_per_gas.unwrap() > U256::from(0); - - let (gas_price, _max_fee_per_gas, _max_priority_fee_per_gas) = { - let details = fee_details(gas_price, None, None)?; - ( - details.gas_price, - details.max_fee_per_gas, - details.max_priority_fee_per_gas, - ) - }; - let block = account_base_app.read().current_block(None); // use given gas limit or query current block's limit let gas_limit = match gas { @@ -427,8 +399,6 @@ impl EthApi for EthApiImpl { value: value.unwrap_or_default(), gas_limit: gas_limit.as_u64(), gas_price, - max_fee_per_gas: None, - max_priority_fee_per_gas: None, nonce, }; @@ -451,8 +421,6 @@ impl EthApi for EthApiImpl { value: value.unwrap_or_default(), gas_limit: gas_limit.as_u64(), gas_price, - max_fee_per_gas: None, - max_priority_fee_per_gas: None, nonce, }; @@ -570,19 +538,12 @@ impl EthApi for EthApiImpl { .read() .current_transaction_statuses(Some(BlockId::Hash(hash))); - let base_fee = block.as_ref().map(|b| { - ::FeeCalculator::min_gas_price( - b.header.number.as_u64(), - ) - }); - match (block, statuses) { (Some(block), Some(statuses)) => Ok(Some(rich_block_build( block, statuses.into_iter().map(Some).collect(), Some(hash), full, - base_fee, ))), _ => Ok(None), } @@ -621,12 +582,6 @@ impl EthApi for EthApiImpl { let block = account_base_app.read().current_block(id.clone()); let statuses = account_base_app.read().current_transaction_statuses(id); - let base_fee = block.as_ref().map(|b| { - ::FeeCalculator::min_gas_price( - b.header.number.as_u64(), - ) - }); - match (block, statuses) { (Some(block), Some(statuses)) => { let hash = block.header.hash(); @@ -636,18 +591,9 @@ impl EthApi for EthApiImpl { statuses.into_iter().map(Some).collect(), Some(hash), full, - base_fee, ))) } - _ => Ok(if let Some(h) = height { - if 0 < h && h < *EVM_FIRST_BLOCK_HEIGHT { - Some(dummy_block(h, full)) - } else { - None - } - } else { - None - }), + _ => Ok(None), } }); @@ -771,54 +717,16 @@ impl EthApi for EthApiImpl { } fn send_raw_transaction(&self, bytes: Bytes) -> BoxFuture> { - let slice = &bytes.0[..]; - if slice.is_empty() { - return Box::pin(future::err(internal_err("transaction data is empty"))); - } - // let first = slice.get(0).unwrap(); - let first = slice.first().unwrap(); - let transaction = if first > &0x7f { - // Legacy transaction. Decode and wrap in envelope. - match rlp::decode::(slice) { - Ok(transaction) => ethereum::TransactionV2::Legacy(transaction), - Err(_) => { - return Box::pin(future::err(internal_err( - "decode transaction failed", - ))); - } - } - } else { - let curr_height = match self.block_number() { - Ok(h) => h.as_u64(), - Err(e) => return Box::pin(future::err(e)), - }; - - if CFG.checkpoint.enable_eip1559_height > curr_height { - return Box::pin(future::err(internal_err(format!( - "eip1559 not enabled at height: {:?}", - curr_height - )))); - } - // Typed Transaction. - // `ethereum` crate decode implementation for `TransactionV2` expects a valid rlp input, - // and EIP-1559 breaks that assumption by prepending a version byte. - // We re-encode the payload input to get a valid rlp, and the decode implementation will strip - // them to check the transaction version byte. - let extend = rlp::encode(&slice); - match rlp::decode::(&extend[..]) { - Ok(transaction) => transaction, - Err(_) => { - return Box::pin(future::err(internal_err( - "decode transaction failed", - ))) - } + let transaction = match rlp::decode::(&bytes.0[..]) { + Ok(transaction) => transaction, + Err(_) => { + return Box::pin(future::err(internal_err("decode transaction failed"))); } }; - debug!(target: "eth_rpc", "send_raw_transaction :{:?}", transaction); - let transaction_hash = transaction.hash(); - + let transaction_hash = + H256::from_slice(Keccak256::digest(&rlp::encode(&transaction)).as_slice()); let function = actions::Action::Ethereum(actions::ethereum::Action::Transact(transaction)); let txn = serde_json::to_vec( @@ -856,25 +764,6 @@ impl EthApi for EthApiImpl { ) -> BoxFuture> { debug!(target: "eth_rpc", "estimate_gas, block number {:?} request:{:?}", number, request); - let _is_eip1559 = request.max_fee_per_gas.is_some() - && request.max_priority_fee_per_gas.is_some() - && request.max_fee_per_gas.unwrap() > U256::from(0) - && request.max_priority_fee_per_gas.unwrap() > U256::from(0); - - let (gas_price, _max_fee_per_gas, _max_priority_fee_per_gas) = { - if let Ok(details) = fee_details(request.gas_price, None, None) { - ( - details.gas_price, - details.max_fee_per_gas, - details.max_priority_fee_per_gas, - ) - } else { - return Box::pin(async move { - Err(internal_err("estimate_gas fee_details err!!!".to_string())) - }); - } - }; - let account_base_app = self.account_base_app.clone(); let task = spawn_blocking(move || { @@ -971,9 +860,7 @@ impl EthApi for EthApiImpl { let CallRequest { from, to, - gas_price: _, - max_fee_per_gas: _, - max_priority_fee_per_gas: _, + gas_price, gas, value, data, @@ -997,8 +884,6 @@ impl EthApi for EthApiImpl { value: value.unwrap_or_default(), gas_limit, gas_price, - max_fee_per_gas: None, - max_priority_fee_per_gas: None, nonce, }; @@ -1023,8 +908,6 @@ impl EthApi for EthApiImpl { value: value.unwrap_or_default(), gas_limit, gas_price, - max_fee_per_gas: None, - max_priority_fee_per_gas: None, nonce, }; @@ -1122,18 +1005,11 @@ impl EthApi for EthApiImpl { } } - let base_fee = Some( - ::FeeCalculator::min_gas_price( - block.header.number.as_u64(), - ), - ); - - Ok(transaction_build( + Ok(Some(transaction_build( block.transactions[index].clone(), Some(block), Some(statuses[index].clone()), - base_fee, - )) + ))) } _ => Ok(None), } @@ -1164,24 +1040,17 @@ impl EthApi for EthApiImpl { .read() .current_transaction_statuses(Some(BlockId::Hash(hash))); - let base_fee = block.as_ref().map(|b| { - ::FeeCalculator::min_gas_price( - b.header.number.as_u64(), - ) - }); - match (block, statuses) { (Some(block), Some(statuses)) => { if index >= block.transactions.len() { return Ok(None); } - Ok(transaction_build( + Ok(Some(transaction_build( block.transactions[index].clone(), Some(block), Some(statuses[index].clone()), - base_fee, - )) + ))) } _ => Ok(None), } @@ -1208,24 +1077,18 @@ impl EthApi for EthApiImpl { let index = index.value(); let block = account_base_app.read().current_block(id.clone()); let statuses = account_base_app.read().current_transaction_statuses(id); + match (block, statuses) { (Some(block), Some(statuses)) => { if index >= block.transactions.len() { return Ok(None); } - let base_fee = Some( - ::FeeCalculator::min_gas_price( - block.header.number.as_u64(), - ), - ); - - Ok(transaction_build( + Ok(Some(transaction_build( block.transactions[index].clone(), Some(block), Some(statuses[index].clone()), - base_fee, - )) + ))) } _ => Ok(None), } @@ -1258,14 +1121,8 @@ impl EthApi for EthApiImpl { .current_transaction_statuses(id.clone()); let receipts = account_base_app.read().current_receipts(id.clone()); - let base_fee = block.as_ref().map(|b| { - ::FeeCalculator::min_gas_price( - b.header.number.as_u64(), - ) - }); - - match (block, statuses, receipts, base_fee) { - (Some(block), Some(statuses), Some(receipts), Some(base_fee)) => { + match (block, statuses, receipts) { + (Some(block), Some(statuses), Some(receipts)) => { if id.is_none() { if let Some(idx) = statuses.iter().position(|t| t.transaction_hash == hash) @@ -1276,6 +1133,7 @@ impl EthApi for EthApiImpl { } } + let _leng = receipts.len(); let block_hash = H256::from_slice( Keccak256::digest(&rlp::encode(&block.header)).as_slice(), ); @@ -1285,15 +1143,6 @@ impl EthApi for EthApiImpl { cumulative_receipts .truncate((status.transaction_index + 1) as usize); - let transaction = block.transactions[index].clone(); - let effective_gas_price = match transaction { - EthereumTransaction::Legacy(t) => t.gas_price, - EthereumTransaction::EIP1559(t) => base_fee - .checked_add(t.max_priority_fee_per_gas) - .unwrap_or_else(U256::max_value), - EthereumTransaction::EIP2930(t) => t.gas_price, - }; - return Ok(Some(Receipt { transaction_hash: Some(status.transaction_hash), transaction_index: Some(status.transaction_index.into()), @@ -1347,7 +1196,6 @@ impl EthApi for EthApiImpl { status_code: Some(U64::from(receipt.state_root.to_low_u64_be())), logs_bloom: receipt.logs_bloom, state_root: None, - effective_gas_price, })); } _ => Ok(None), @@ -1459,62 +1307,33 @@ impl EthApi for EthApiImpl { } pub fn sign_transaction_message( - message: TransactionMessage, + message: EthereumTransactionMessage, private_key: &H256, ) -> ruc::Result { - match message { - TransactionMessage::Legacy(m) => { - let signing_message = libsecp256k1::Message::parse_slice(&m.hash()[..]) - .map_err(|_| eg!("invalid signing message"))?; - let secret = &libsecp256k1::SecretKey::parse_slice(&private_key[..]) - .map_err(|_| eg!("invalid secret"))?; - let (signature, recid) = libsecp256k1::sign(&signing_message, secret); - - let v = match m.chain_id { - None => 27 + recid.serialize() as u64, - Some(chain_id) => 2 * chain_id + 35 + recid.serialize() as u64, - }; - let rs = signature.serialize(); - let r = H256::from_slice(&rs[0..32]); - let s = H256::from_slice(&rs[32..64]); - - Ok(EthereumTransaction::Legacy(ethereum::LegacyTransaction { - nonce: m.nonce, - gas_price: m.gas_price, - gas_limit: m.gas_limit, - action: m.action, - value: m.value, - input: m.input, - signature: ethereum::TransactionSignature::new(v, r, s) - .ok_or(eg!("signer generated invalid signature"))?, - })) - } - TransactionMessage::EIP1559(m) => { - let signing_message = libsecp256k1::Message::parse_slice(&m.hash()[..]) - .map_err(|_| eg!("invalid signing message"))?; - let secret = &libsecp256k1::SecretKey::parse_slice(&private_key[..]) - .map_err(|_| eg!("invalid secret"))?; - let (signature, recid) = libsecp256k1::sign(&signing_message, secret); - let rs = signature.serialize(); - let r = H256::from_slice(&rs[0..32]); - let s = H256::from_slice(&rs[32..64]); - - Ok(EthereumTransaction::EIP1559(ethereum::EIP1559Transaction { - chain_id: m.chain_id, - nonce: m.nonce, - max_priority_fee_per_gas: m.max_priority_fee_per_gas, - max_fee_per_gas: m.max_fee_per_gas, - gas_limit: m.gas_limit, - action: m.action, - value: m.value, - input: m.input.clone(), - access_list: m.access_list, - odd_y_parity: recid.serialize() != 0, - r, - s, - })) - } - } + let signing_message = libsecp256k1::Message::parse_slice(&message.hash()[..]) + .map_err(|_| eg!("invalid signing message"))?; + let secret = &libsecp256k1::SecretKey::parse_slice(&private_key[..]) + .map_err(|_| eg!("invalid secret"))?; + let (signature, recid) = libsecp256k1::sign(&signing_message, secret); + + let v = match message.chain_id { + None => 27 + recid.serialize() as u64, + Some(chain_id) => 2 * chain_id + 35 + recid.serialize() as u64, + }; + let rs = signature.serialize(); + let r = H256::from_slice(&rs[0..32]); + let s = H256::from_slice(&rs[32..64]); + + Ok(EthereumTransaction { + nonce: message.nonce, + gas_price: message.gas_price, + gas_limit: message.gas_limit, + action: message.action, + value: message.value, + input: message.input, + signature: ethereum::TransactionSignature::new(v, r, s) + .ok_or(eg!("signer generated invalid signature"))?, + }) } fn rich_block_build( @@ -1522,7 +1341,6 @@ fn rich_block_build( statuses: Vec>, hash: Option, full_transactions: bool, - base_fee: Option, ) -> RichBlock { Rich { inner: Block { @@ -1558,12 +1376,11 @@ fn rich_block_build( .transactions .iter() .enumerate() - .filter_map(|(index, transaction)| { + .map(|(index, transaction)| { transaction_build( transaction.clone(), Some(block.clone()), Some(statuses[index].clone().unwrap_or_default()), - base_fee, ) }) .collect(), @@ -1586,141 +1403,82 @@ fn rich_block_build( } }, size: Some(U256::from(rlp::encode(&block).len() as u32)), - base_fee_per_gas: base_fee, }, extra_info: BTreeMap::new(), } } fn transaction_build( - ethereum_transaction: EthereumTransaction, - block: Option>, + transaction: EthereumTransaction, + block: Option, status: Option, - base_fee: Option, -) -> Option { - let mut transaction: Transaction = ethereum_transaction.clone().into(); - - match ðereum_transaction { - EthereumTransaction::EIP1559(_) => { - if block.is_none() && status.is_none() { - transaction.gas_price = transaction.max_fee_per_gas; - } else { - let base_fee = base_fee.unwrap_or(U256::zero()); - let max_priority_fee_per_gas = - transaction.max_priority_fee_per_gas.unwrap_or(U256::zero()); - transaction.gas_price = Some( - base_fee - .checked_add(max_priority_fee_per_gas) - .unwrap_or_else(U256::max_value), - ); - } - } - EthereumTransaction::Legacy(_) => { - transaction.max_fee_per_gas = None; - transaction.max_priority_fee_per_gas = None; - } - _ => return None, - } - - let pubkey = match public_key(ðereum_transaction) { +) -> Transaction { + let pubkey = match public_key(&transaction) { Ok(p) => Some(p), Err(_e) => None, }; - // Block hash. - // transaction.block_hash = block.as_ref().map_or(None, |block| { - // Some(H256::from_slice( - // Keccak256::digest(&rlp::encode(&block.header)).as_slice(), - // )) - // }); - transaction.block_hash = block.as_ref().map(|block| { - H256::from_slice(Keccak256::digest(&rlp::encode(&block.header)).as_slice()) - }); - - // Block number. - transaction.block_number = block.as_ref().map(|block| block.header.number); - // Transaction index. - - transaction.transaction_index = status - .as_ref() - .map(|status| U256::from(status.transaction_index)); - - transaction.from = status.as_ref().map_or( - { - match pubkey { - Some(pk) => { - H160::from(H256::from_slice(Keccak256::digest(pk).as_slice())) - } - _ => H160::default(), - } - }, - |status| status.from, - ); - // To. - transaction.to = status.as_ref().map_or( - { - let action = match ethereum_transaction.clone() { - EthereumTransaction::Legacy(t) => t.action, - EthereumTransaction::EIP1559(t) => t.action, - EthereumTransaction::EIP2930(t) => t.action, - }; - match action { - ethereum::TransactionAction::Call(to) => Some(to), - _ => None, - } - }, - |status| status.to, - ); - // Creates. - // transaction.creates = status - // .as_ref() - // .map_or(None, |status| status.contract_address); - transaction.creates = status.as_ref().and_then(|status| status.contract_address); - - // Public key. - transaction.public_key = pubkey.as_ref().map(H512::from); - - transaction.hash = if let Some(status) = &status { + let hash = if let Some(status) = &status { status.transaction_hash } else { - match ethereum_transaction { - EthereumTransaction::Legacy(t) => { - H256::from_slice(Keccak256::digest(&rlp::encode(&t)).as_slice()) - } - EthereumTransaction::EIP1559(t) => { - H256::from_slice(Keccak256::digest(&rlp::encode(&t)).as_slice()) - } - EthereumTransaction::EIP2930(_) => return None, - } + H256::from_slice(Keccak256::digest(&rlp::encode(&transaction)).as_slice()) }; - Some(transaction) + Transaction { + hash, + nonce: transaction.nonce, + block_hash: block.as_ref().map(|block| { + H256::from_slice(Keccak256::digest(&rlp::encode(&block.header)).as_slice()) + }), + block_number: block.as_ref().map(|block| block.header.number), + transaction_index: status + .as_ref() + .map(|status| U256::from(status.transaction_index)), + from: status.as_ref().map_or( + { + match pubkey { + Some(pk) => { + H160::from(H256::from_slice(Keccak256::digest(pk).as_slice())) + } + _ => H160::default(), + } + }, + |status| status.from, + ), + to: status.as_ref().map_or( + { + match transaction.action { + ethereum::TransactionAction::Call(to) => Some(to), + _ => None, + } + }, + |status| status.to, + ), + value: transaction.value, + gas_price: transaction.gas_price, + gas: transaction.gas_limit, + input: Bytes(transaction.clone().input), + creates: status.as_ref().and_then(|status| status.contract_address), + raw: Bytes(rlp::encode(&transaction).to_vec()), + public_key: pubkey.as_ref().map(H512::from), + chain_id: transaction.signature.chain_id().map(U64::from), + standard_v: U256::from(transaction.signature.standard_v()), + v: U256::from(transaction.signature.v()), + r: U256::from(transaction.signature.r().as_bytes()), + s: U256::from(transaction.signature.s().as_bytes()), + } } pub fn public_key(transaction: &EthereumTransaction) -> ruc::Result<[u8; 64]> { let mut sig = [0u8; 65]; let mut msg = [0u8; 32]; - match transaction { - EthereumTransaction::Legacy(t) => { - sig[0..32].copy_from_slice(&t.signature.r()[..]); - sig[32..64].copy_from_slice(&t.signature.s()[..]); - sig[64] = t.signature.standard_v(); - msg.copy_from_slice( - ðereum::LegacyTransactionMessage::from(t.clone()).hash()[..], - ); - } - EthereumTransaction::EIP1559(t) => { - sig[0..32].copy_from_slice(&t.r[..]); - sig[32..64].copy_from_slice(&t.s[..]); - sig[64] = t.odd_y_parity as u8; - msg.copy_from_slice( - ðereum::EIP1559TransactionMessage::from(t.clone()).hash()[..], - ); - } - _ => { - return Err(eg!("Transaction Type Error")); - } - } + sig[0..32].copy_from_slice(&transaction.signature.r()[..]); + sig[32..64].copy_from_slice(&transaction.signature.s()[..]); + sig[64] = transaction.signature.standard_v(); + msg.copy_from_slice( + &EthereumTransactionMessage::from(transaction.clone()).hash()[..], + ); + fp_types::crypto::secp256k1_ecdsa_recover(&sig, &msg) } @@ -1852,45 +1610,6 @@ fn native_block_id(number: Option) -> Option { } } -struct FeeDetails { - gas_price: Option, - max_fee_per_gas: Option, - max_priority_fee_per_gas: Option, -} - -fn fee_details( - request_gas_price: Option, - request_max_fee: Option, - request_priority: Option, -) -> Result { - match (request_gas_price, request_max_fee, request_priority) { - (gas_price, None, None) => { - // Legacy request, all default to gas price. - Ok(FeeDetails { - gas_price, - max_fee_per_gas: gas_price, - max_priority_fee_per_gas: gas_price, - }) - } - (_, max_fee, max_priority) => { - // eip-1559 - // Ensure `max_priority_fee_per_gas` is less or equal to `max_fee_per_gas`. - if let Some(max_priority) = max_priority { - let max_fee = max_fee.unwrap_or_default(); - if max_priority > max_fee { - return Err(internal_err( - "Invalid input: `max_priority_fee_per_gas` greater than `max_fee_per_gas`" - )); - } - } - Ok(FeeDetails { - gas_price: max_fee, - max_fee_per_gas: max_fee, - max_priority_fee_per_gas: max_priority, - }) - } - } -} fn dummy_block(height: u64, full: bool) -> Rich { let hash = if height == *EVM_FIRST_BLOCK_HEIGHT - 1 { H256([0; 32]) @@ -1907,9 +1626,6 @@ fn dummy_block(height: u64, full: bool) -> Rich { BlockTransactions::Hashes(vec![]) }; - let gas_price = - ::FeeCalculator::min_gas_price(height); - let inner = Block { hash: Some(hash), parent_hash, @@ -1945,7 +1661,6 @@ fn dummy_block(height: u64, full: bool) -> Rich { uncles: vec![], transactions, size: Some(U256::from(0x1_u32)), - base_fee_per_gas: Some(gas_price), }; Rich { diff --git a/src/components/contracts/rpc/src/eth_filter.rs b/src/components/contracts/rpc/src/eth_filter.rs index 7dce5b914..18c71814d 100644 --- a/src/components/contracts/rpc/src/eth_filter.rs +++ b/src/components/contracts/rpc/src/eth_filter.rs @@ -1,6 +1,6 @@ use crate::{filter_block_logs, internal_err}; use baseapp::BaseApp; -use ethereum::BlockV2 as EthereumBlock; +use ethereum::BlockV0 as EthereumBlock; use ethereum_types::{H256, U256}; use fp_evm::{BlockId, TransactionStatus}; use fp_rpc_core::types::{ diff --git a/src/components/contracts/rpc/src/eth_pubsub.rs b/src/components/contracts/rpc/src/eth_pubsub.rs index ffa007b57..21efe3166 100644 --- a/src/components/contracts/rpc/src/eth_pubsub.rs +++ b/src/components/contracts/rpc/src/eth_pubsub.rs @@ -1,6 +1,6 @@ use baseapp::tm_events::{get_pendingtx, get_sync_status}; use baseapp::BaseApp; -use ethereum::{BlockV2 as EthereumBlock, ReceiptV0 as Receipt}; +use ethereum::{BlockV0 as EthereumBlock, ReceiptV0 as Receipt}; use ethereum_types::{H256, U256}; use fp_evm::BlockId; use fp_rpc_core::types::pubsub::PubSubSyncStatus; diff --git a/src/components/finutils/Cargo.toml b/src/components/finutils/Cargo.toml index 83bf14733..1782f2f98 100644 --- a/src/components/finutils/Cargo.toml +++ b/src/components/finutils/Cargo.toml @@ -22,7 +22,7 @@ serde = { version = "1.0.124", features = ["derive"] } sha2 = "0.10" tokio = "1.10.1" -wasm-bindgen = { version = "0.2.83", features = ["serde-serialize"] } +wasm-bindgen = { version = "=0.2.73", features = ["serde-serialize"] } getrandom = "0.2" noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } diff --git a/src/components/finutils/src/txn_builder/mod.rs b/src/components/finutils/src/txn_builder/mod.rs index d4afbd1e5..102cba254 100644 --- a/src/components/finutils/src/txn_builder/mod.rs +++ b/src/components/finutils/src/txn_builder/mod.rs @@ -635,6 +635,7 @@ impl TransactionBuilder { /// * `enc_key` - XPublicKey of OwnerMemo encryption of receiver /// * `is_bar_transparent` - if transparent bar (ar) #[allow(clippy::too_many_arguments)] + pub fn add_operation_bar_to_abar( &mut self, seed: [u8; 32], diff --git a/src/components/wallet_mobile/Cargo.toml b/src/components/wallet_mobile/Cargo.toml index d84459968..53086d49a 100644 --- a/src/components/wallet_mobile/Cargo.toml +++ b/src/components/wallet_mobile/Cargo.toml @@ -60,7 +60,7 @@ features = [ jni = "0.20" [target.'cfg(target_arch="wasm32")'.dependencies] -wasm-bindgen = { version = "0.2.83", features = ["serde-serialize"] } +wasm-bindgen = { version = "=0.2.73", features = ["serde-serialize"] } [target.'cfg(not(target_arch="wasm32"))'.dependencies] safer-ffi = "0.0.10" diff --git a/src/components/wasm/Cargo.toml b/src/components/wasm/Cargo.toml index 970cb8c68..fbd9de16d 100644 --- a/src/components/wasm/Cargo.toml +++ b/src/components/wasm/Cargo.toml @@ -24,7 +24,7 @@ rand_chacha = "0.3" rand_core = { version = "0.6", default-features = false, features = ["alloc"] } serde = { version = "1.0.124", features = ["derive"] } serde_json = "1.0" -wasm-bindgen = { version = "0.2.83", features = ["serde-serialize"] } +wasm-bindgen = { version = "=0.2.73", features = ["serde-serialize"] } bs58 = "0.4" ring = "0.16.19" @@ -71,7 +71,7 @@ features = [ serde = "1.0.124" serde_json = "1.0.41" vergen = "=3.1.0" -wasm-bindgen = { version = "0.2.83", features = ["serde-serialize"] } +wasm-bindgen = { version = "=0.2.73", features = ["serde-serialize"] } [dev-dependencies] # Must enable the "js"-feature, diff --git a/src/libs/bitmap/src/lib.rs b/src/libs/bitmap/src/lib.rs index c3dbe68ca..fbf2bed15 100644 --- a/src/libs/bitmap/src/lib.rs +++ b/src/libs/bitmap/src/lib.rs @@ -566,7 +566,7 @@ fn count_byte(mask: usize) -> u8 { let mut result = 0; for i in 0..8 { - result += u8::from(mask & (1 << i) != 0); + result += (mask & (1 << i) != 0) as u8; } result diff --git a/src/libs/credentials/Cargo.toml b/src/libs/credentials/Cargo.toml index 021e14dad..8b1819d3a 100644 --- a/src/libs/credentials/Cargo.toml +++ b/src/libs/credentials/Cargo.toml @@ -11,6 +11,6 @@ rand_core = { version = "0.6", default-features = false, features = ["alloc"] } linear-map = {version = "1.2.0", features = ["serde_impl"] } serde = "1.0.124" serde_derive = "1.0" -wasm-bindgen = { version = "0.2.83", features = ["serde-serialize"] } +wasm-bindgen = { version = "=0.2.73", features = ["serde-serialize"] } noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } From cfc20a410eb196cb271bfa0688bf6af3bc30c305 Mon Sep 17 00:00:00 2001 From: harry Date: Fri, 6 Jan 2023 09:28:29 +0800 Subject: [PATCH 03/10] simplify eip1559 support eip1559 wasm support --- src/components/config/src/abci/mod.rs | 3 + .../contracts/primitives/rpc-core/Cargo.toml | 1 + .../primitives/rpc-core/src/types/block.rs | 6 +- .../rpc-core/src/types/call_request.rs | 4 + .../primitives/rpc-core/src/types/receipt.rs | 2 + .../rpc-core/src/types/transaction.rs | 16 +- .../rpc-core/src/types/transaction_request.rs | 13 +- .../primitives/types/src/actions/ethereum.rs | 8 +- .../primitives/types/src/actions/mod.rs | 8 + .../primitives/types/src/assemble.rs | 5 +- .../contracts/primitives/wasm/Cargo.toml | 3 + .../contracts/primitives/wasm/src/wasm.rs | 90 ++++++-- src/components/contracts/rpc/src/eth.rs | 216 ++++++++++++++++-- 13 files changed, 330 insertions(+), 45 deletions(-) diff --git a/src/components/config/src/abci/mod.rs b/src/components/config/src/abci/mod.rs index b97a41c6b..f20193426 100644 --- a/src/components/config/src/abci/mod.rs +++ b/src/components/config/src/abci/mod.rs @@ -88,6 +88,7 @@ pub struct CheckPointConfig { // Fix the amount in the delegators that staking did not modify when it punished the validator. pub fix_delegators_am_height: u64, pub validators_limit_v2_height: u64, + pub enable_eip1559_height: u64, } impl CheckPointConfig { @@ -127,6 +128,7 @@ impl CheckPointConfig { proper_gas_set_height: 0, fix_delegators_am_height: 0, validators_limit_v2_height: 0, + enable_eip1559_height: 0, }; #[cfg(not(feature = "debug_env"))] let config = CheckPointConfig { @@ -156,6 +158,7 @@ impl CheckPointConfig { fix_undelegation_missing_reward_height: 3000000, fix_delegators_am_height: 30000000, validators_limit_v2_height: 30000000, + enable_eip1559_height: 40000000, }; let content = toml::to_string(&config).unwrap(); file.write_all(content.as_bytes()).unwrap(); diff --git a/src/components/contracts/primitives/rpc-core/Cargo.toml b/src/components/contracts/primitives/rpc-core/Cargo.toml index 81617b82f..fe9bee55a 100644 --- a/src/components/contracts/primitives/rpc-core/Cargo.toml +++ b/src/components/contracts/primitives/rpc-core/Cargo.toml @@ -9,6 +9,7 @@ description = "RPC traits of Ethereum." license = "GPL-3.0-or-later WITH Classpath-exception-2.0" [dependencies] +ethereum = { version = "0.12.0", default-features = false, features = ["with-serde"] } ethereum-types = "0.13.1" futures = "0.3.16" jsonrpc-core = { git = "https://github.com/FindoraNetwork/jsonrpc.git", package = "jsonrpc-core" } diff --git a/src/components/contracts/primitives/rpc-core/src/types/block.rs b/src/components/contracts/primitives/rpc-core/src/types/block.rs index 5786136da..bd1d762c6 100644 --- a/src/components/contracts/primitives/rpc-core/src/types/block.rs +++ b/src/components/contracts/primitives/rpc-core/src/types/block.rs @@ -21,8 +21,7 @@ use std::ops::Deref; use crate::types::{Bytes, Transaction}; use ethereum_types::{Bloom as H2048, H160, H256, U256}; -use serde::ser::Error; -use serde::{Serialize, Serializer}; +use serde::{ser::Error, Serialize, Serializer}; /// Block Transactions #[derive(Debug)] @@ -90,6 +89,9 @@ pub struct Block { pub transactions: BlockTransactions, /// Size in bytes pub size: Option, + /// Base Fee for post-EIP1559 blocks. + #[serde(skip_serializing_if = "Option::is_none")] + pub base_fee_per_gas: Option, } /// Block header representation. diff --git a/src/components/contracts/primitives/rpc-core/src/types/call_request.rs b/src/components/contracts/primitives/rpc-core/src/types/call_request.rs index 0451dbaf6..2e965b9c9 100644 --- a/src/components/contracts/primitives/rpc-core/src/types/call_request.rs +++ b/src/components/contracts/primitives/rpc-core/src/types/call_request.rs @@ -31,6 +31,10 @@ pub struct CallRequest { pub to: Option, /// Gas Price pub gas_price: Option, + /// EIP-1559 Max base fee the caller is willing to pay + pub max_fee_per_gas: Option, + /// EIP-1559 Priority fee the caller is paying to the block author + pub max_priority_fee_per_gas: Option, /// Gas pub gas: Option, /// Value diff --git a/src/components/contracts/primitives/rpc-core/src/types/receipt.rs b/src/components/contracts/primitives/rpc-core/src/types/receipt.rs index 5d1ed929e..af4542f75 100644 --- a/src/components/contracts/primitives/rpc-core/src/types/receipt.rs +++ b/src/components/contracts/primitives/rpc-core/src/types/receipt.rs @@ -54,4 +54,6 @@ pub struct Receipt { // NOTE(niklasad1): Unknown after EIP98 rules, if it's missing then skip serializing it #[serde(skip_serializing_if = "Option::is_none", rename = "status")] pub status_code: Option, + /// Effective gas price. Pre-eip1559 this is just the gasprice. Post-eip1559 this is base fee + priority fee. + pub effective_gas_price: U256, } diff --git a/src/components/contracts/primitives/rpc-core/src/types/transaction.rs b/src/components/contracts/primitives/rpc-core/src/types/transaction.rs index 6d767f40c..6bc36743a 100644 --- a/src/components/contracts/primitives/rpc-core/src/types/transaction.rs +++ b/src/components/contracts/primitives/rpc-core/src/types/transaction.rs @@ -17,9 +17,9 @@ // along with this program. If not, see . use crate::types::Bytes; +use ethereum::AccessListItem; use ethereum_types::{H160, H256, H512, U256, U64}; -use serde::ser::SerializeStruct; -use serde::{Serialize, Serializer}; +use serde::{ser::SerializeStruct, Serialize, Serializer}; use std::{ collections::HashMap, sync::{Arc, Mutex}, @@ -46,7 +46,14 @@ pub struct Transaction { /// Transfered value pub value: U256, /// Gas Price - pub gas_price: U256, + #[serde(skip_serializing_if = "Option::is_none")] + pub gas_price: Option, + /// eip1559. Max BaseFeePerGas the user is willing to pay. + #[serde(skip_serializing_if = "Option::is_none")] + pub max_fee_per_gas: Option, + /// eip1559.The miner's tip. + #[serde(skip_serializing_if = "Option::is_none")] + pub max_priority_fee_per_gas: Option, /// Gas pub gas: U256, /// Data @@ -67,6 +74,9 @@ pub struct Transaction { pub r: U256, /// The S field of the signature. pub s: U256, + /// eip1559. Pre-pay to warm storage access. + #[cfg_attr(feature = "std", serde(skip_serializing_if = "Option::is_none"))] + pub access_list: Option>, } /// Local Transaction Status diff --git a/src/components/contracts/primitives/rpc-core/src/types/transaction_request.rs b/src/components/contracts/primitives/rpc-core/src/types/transaction_request.rs index bbddf8d5f..c5ab601a6 100644 --- a/src/components/contracts/primitives/rpc-core/src/types/transaction_request.rs +++ b/src/components/contracts/primitives/rpc-core/src/types/transaction_request.rs @@ -19,11 +19,12 @@ //! `TransactionRequest` type use crate::types::Bytes; +use ethereum::AccessListItem; use ethereum_types::{H160, U256}; use serde::{Deserialize, Serialize}; /// Transaction request coming from RPC -#[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Serialize, Deserialize)] +#[derive(Debug, Clone, Default, Eq, PartialEq, Serialize, Deserialize)] #[serde(deny_unknown_fields)] #[serde(rename_all = "camelCase")] pub struct TransactionRequest { @@ -32,7 +33,14 @@ pub struct TransactionRequest { /// Recipient pub to: Option, /// Gas Price + #[serde(default)] pub gas_price: Option, + /// Max BaseFeePerGas the user is willing to pay. + #[serde(default)] + pub max_fee_per_gas: Option, + /// The miner's tip. + #[serde(default)] + pub max_priority_fee_per_gas: Option, /// Gas pub gas: Option, /// Value of transaction in wei @@ -41,4 +49,7 @@ pub struct TransactionRequest { pub data: Option, /// Transaction's nonce pub nonce: Option, + /// Pre-pay to warm storage access. + #[serde(default)] + pub access_list: Option>, } diff --git a/src/components/contracts/primitives/types/src/actions/ethereum.rs b/src/components/contracts/primitives/types/src/actions/ethereum.rs index 5d2403a08..ce6271f04 100644 --- a/src/components/contracts/primitives/types/src/actions/ethereum.rs +++ b/src/components/contracts/primitives/types/src/actions/ethereum.rs @@ -1,7 +1,13 @@ -use ethereum::TransactionV0 as Transaction; +use ethereum::TransactionV0 as LegcayTransaction; +use ethereum::TransactionV2 as Transaction; use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum Action { + Transact(LegcayTransaction), +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub enum Action2 { Transact(Transaction), } diff --git a/src/components/contracts/primitives/types/src/actions/mod.rs b/src/components/contracts/primitives/types/src/actions/mod.rs index b049ae7d2..4e07c8407 100644 --- a/src/components/contracts/primitives/types/src/actions/mod.rs +++ b/src/components/contracts/primitives/types/src/actions/mod.rs @@ -12,3 +12,11 @@ pub enum Action { XHub(xhub::Action), Template(template::Action), } + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub enum Action2 { + Ethereum(ethereum::Action2), + Evm(evm::Action), + XHub(xhub::Action), + Template(template::Action), +} diff --git a/src/components/contracts/primitives/types/src/assemble.rs b/src/components/contracts/primitives/types/src/assemble.rs index 41cdb5a16..879b3dfff 100644 --- a/src/components/contracts/primitives/types/src/assemble.rs +++ b/src/components/contracts/primitives/types/src/assemble.rs @@ -1,5 +1,5 @@ use crate::actions::ethereum::Action as EtherAction; -use crate::actions::Action; +use crate::actions::{Action, Action2}; use crate::crypto::{Address, Signature}; use crate::transaction; use ethereum::TransactionV0 as Transaction; @@ -32,6 +32,9 @@ impl CheckFee { pub type UncheckedTransaction = transaction::UncheckedTransaction; +pub type UncheckedTransaction2 = + transaction::UncheckedTransaction; + /// Transaction type that has already been checked. pub type CheckedTransaction = transaction::CheckedTransaction; diff --git a/src/components/contracts/primitives/wasm/Cargo.toml b/src/components/contracts/primitives/wasm/Cargo.toml index 7a35e137b..cf8cc46db 100644 --- a/src/components/contracts/primitives/wasm/Cargo.toml +++ b/src/components/contracts/primitives/wasm/Cargo.toml @@ -27,6 +27,9 @@ wasm-bindgen = { version = "=0.2.73", features = ["serde-serialize"] } # Must enable the "js"-feature, # OR the compiling will fail. getrandom = { version = "0.2", features = ["js"] } +baseapp = { path = "../../../contracts/baseapp" } +module-ethereum = { path = "../../modules/ethereum"} +fp-traits = { path = "../../primitives/traits" } [lib] crate-type = ["cdylib", "rlib"] diff --git a/src/components/contracts/primitives/wasm/src/wasm.rs b/src/components/contracts/primitives/wasm/src/wasm.rs index f587e244c..ac75067dd 100644 --- a/src/components/contracts/primitives/wasm/src/wasm.rs +++ b/src/components/contracts/primitives/wasm/src/wasm.rs @@ -1,11 +1,17 @@ #![allow(clippy::unused_unit)] use core::fmt::Display; -use ethereum::{LegacyTransactionMessage, TransactionV0 as Transaction}; +use ethereum::{ + LegacyTransactionMessage,TransactionSignature, + TransactionV0 as LegacyTransaction, TransactionV2, +}; use ethereum_types::{H160, H256}; + use fp_types::{ - actions::{ethereum::Action as EthAction, Action}, - assemble::UncheckedTransaction, + actions::{ + ethereum::Action2 as EthAction2, Action2, + }, + assemble::{UncheckedTransaction2}, crypto::secp256k1_ecdsa_recover, }; use fp_utils::tx::EvmRawTxWrapper; @@ -13,13 +19,16 @@ use ruc::{d, err::RucResult}; use sha3::{Digest, Keccak256}; use wasm_bindgen::prelude::*; +use baseapp::BaseApp; +use fp_traits::evm::FeeCalculator; + #[inline(always)] pub(crate) fn error_to_jsvalue(e: T) -> JsValue { JsValue::from_str(&e.to_string()) } #[inline(always)] -pub fn recover_signer(transaction: &Transaction) -> Option { +pub fn recover_signer(transaction: &LegacyTransaction) -> Option { let mut sig = [0u8; 65]; let mut msg = [0u8; 32]; sig[0..32].copy_from_slice(&transaction.signature.r()[..]); @@ -29,7 +38,7 @@ pub fn recover_signer(transaction: &Transaction) -> Option { let pubkey = secp256k1_ecdsa_recover(&sig, &msg).ok()?; Some(H160::from(H256::from_slice( - Keccak256::digest(pubkey).as_slice(), + Keccak256::digest(&pubkey).as_slice(), ))) } @@ -42,10 +51,14 @@ pub fn recover_tx_signer(raw_tx: String) -> Result { .c(d!()) .map_err(error_to_jsvalue)?; - let unchecked_tx: UncheckedTransaction<()> = serde_json::from_slice(raw_tx) + let unchecked_tx: UncheckedTransaction2<()> = serde_json::from_slice(raw_tx) .c(d!()) .map_err(error_to_jsvalue)?; - if let Action::Ethereum(EthAction::Transact(tx)) = unchecked_tx.function { + if let Action2::Ethereum(EthAction2::Transact(tx)) = unchecked_tx.function { + let tx = match new_tx2legcay_tx(tx) { + Some(tx) => tx, + None => return Err(error_to_jsvalue("invalid raw tx")), + }; let signer = recover_signer(&tx).c(d!()).map_err(error_to_jsvalue)?; Ok(format!("{:?}", signer)) } else { @@ -62,10 +75,14 @@ pub fn evm_tx_hash(raw_tx: String) -> Result { .c(d!()) .map_err(error_to_jsvalue)?; - let unchecked_tx: UncheckedTransaction<()> = serde_json::from_slice(raw_tx) + let unchecked_tx: UncheckedTransaction2<()> = serde_json::from_slice(raw_tx) .c(d!()) .map_err(error_to_jsvalue)?; - if let Action::Ethereum(EthAction::Transact(tx)) = unchecked_tx.function { + if let Action2::Ethereum(EthAction2::Transact(tx)) = unchecked_tx.function { + let tx = match new_tx2legcay_tx(tx) { + Some(tx) => tx, + None => return Err(error_to_jsvalue("invalid raw tx")), + }; let hash = H256::from_slice(Keccak256::digest(&rlp::encode(&tx)).as_slice()); Ok(format!("{:?}", hash)) } else { @@ -73,24 +90,56 @@ pub fn evm_tx_hash(raw_tx: String) -> Result { } } +fn new_tx2legcay_tx(tx: TransactionV2) -> Option { + let transaction: LegacyTransaction = match tx { + ethereum::TransactionV2::Legacy(tx) => tx, + ethereum::TransactionV2::EIP1559(tx) => { + let min_gas_price_eip1559 = + ::FeeCalculator::min_gas_price(0); + let chain_id: u64 = ::ChainId::get(); + let v: u64 = if tx.odd_y_parity { + chain_id * 2 + 36 + } else { + chain_id * 2 + 35 + }; + let signature = match TransactionSignature::new(v, tx.r, tx.s) { + Some(sig) => sig, + None => return None, + }; + + ethereum::TransactionV0 { + nonce: tx.nonce, + gas_price: min_gas_price_eip1559, + gas_limit: tx.gas_limit, + action: tx.action, + value: tx.value, + input: tx.input, + signature, + } + } + _ => return None, + }; + + Some(transaction) +} + #[cfg(test)] #[allow(missing_docs)] mod test { use super::*; - use fp_types::actions::Action; #[test] fn recover_signer_works() { - let raw_tx = String::from("ZXZtOnsic2lnbmF0dXJlIjpudWxsLCJmdW5jdGlvbiI6eyJFdGhlcmV1bSI6eyJUcmFuc2FjdCI6eyJub25jZSI6IjB4MSIsImdhc19wcmljZSI6IjB4MTc0ODc2ZTgwMCIsImdhc19saW1pdCI6IjB4NTIwOCIsImFjdGlvbiI6eyJDYWxsIjoiMHgyYWQzMjg0NmM2ZGQyZmZkM2VkYWRiZTUxY2Q1YWUwNGFhNWU1NzVlIn0sInZhbHVlIjoiMHg1NmJjNzVlMmQ2MzEwMDAwMCIsImlucHV0IjpbXSwic2lnbmF0dXJlIjp7InYiOjEwODIsInIiOiIweGY4YWVmN2Y4MDUzZDg5ZmVlMzk1MGM0ZDcwMjA4MGJmM2E4MDcyYmVkNWQ4NGEzYWYxOWEzNjAwODFiNjM2YTIiLCJzIjoiMHgyOTYyOTlhOGYyNDMwYjg2ZmQzZWI5NzZlYWJjNzMwYWMxY2ZiYmJlMzZlYjY5ZWFlMzM4Y2ZmMzNjNGE5OGMxIn19fX19"); + let raw_tx = String::from("eyJzaWduYXR1cmUiOm51bGwsImZ1bmN0aW9uIjp7IkV0aGVyZXVtIjp7IlRyYW5zYWN0Ijp7IkxlZ2FjeSI6eyJub25jZSI6IjB4MCIsImdhc19wcmljZSI6IjB4MjU0MGJlNDAwIiwiZ2FzX2xpbWl0IjoiMHgxMDAwMDAiLCJhY3Rpb24iOnsiQ2FsbCI6IjB4MzMyNWE3ODQyNWYxN2E3ZTQ4N2ViNTY2NmIyYmZkOTNhYmIwNmM3MCJ9LCJ2YWx1ZSI6IjB4YSIsImlucHV0IjpbXSwic2lnbmF0dXJlIjp7InYiOjQzNDAsInIiOiIweDZiMjBjNzIzNTEzOTk4ZThmYTQ4NWM1MmI4ZjlhZTRmZDdiMWUwYmQwZGZiNzk4NTIzMThiMGMxMDBlOTFmNWUiLCJzIjoiMHg0ZDRjOGMxZjJlMTdjMDJjNGE4OTZlMjYyMTI3YjhiZDZlYmZkNWY1YTc1NWEzZTkyMjBjZmM2OGI4YzY5ZDVkIn19fX19fQ=="); let tx_bytes = base64::decode_config(raw_tx, base64::URL_SAFE).unwrap(); - let evm_tx = EvmRawTxWrapper::unwrap(&tx_bytes).unwrap(); - let unchecked_tx: UncheckedTransaction<()> = - serde_json::from_slice(evm_tx).unwrap(); - if let Action::Ethereum(EthAction::Transact(tx)) = unchecked_tx.function { + let unchecked_tx: UncheckedTransaction2<()> = + serde_json::from_slice(tx_bytes.as_slice()).unwrap(); + if let Action2::Ethereum(EthAction2::Transact(tx)) = unchecked_tx.function { + let tx: LegacyTransaction = new_tx2legcay_tx(tx).unwrap(); let signer = recover_signer(&tx).unwrap(); assert_eq!( format!("{:?}", signer), - "0xa5225cbee5052100ec2d2d94aa6d258558073757" + "0x5050a4f4b3f9338c3472dcc01a87c76a144b3c9c" ); } else { panic!() @@ -99,15 +148,16 @@ mod test { #[test] fn evm_tx_hash_works() { - let raw_tx = String::from("eyJzaWduYXR1cmUiOm51bGwsImZ1bmN0aW9uIjp7IkV0aGVyZXVtIjp7IlRyYW5zYWN0Ijp7Im5vbmNlIjoiMHg5IiwiZ2FzX3ByaWNlIjoiMHhlOGQ0YTUxMDAwIiwiZ2FzX2xpbWl0IjoiMHg1MjA4IiwiYWN0aW9uIjp7IkNhbGwiOiIweGE1MjI1Y2JlZTUwNTIxMDBlYzJkMmQ5NGFhNmQyNTg1NTgwNzM3NTcifSwidmFsdWUiOiIweDk4YTdkOWI4MzE0YzAwMDAiLCJpbnB1dCI6W10sInNpZ25hdHVyZSI6eyJ2IjoxMDgyLCJyIjoiMHg4MDBjZjQ5ZTAzMmJhYzY4MjY3MzdhZGJhZDEzN2Y0MTk5OTRjNjgxZWE1ZDUyYjliMGJhZDJmNDAyYjMwMTI0IiwicyI6IjB4Mjk1Mjc3ZWY2NTYzNDAwY2VkNjFiODhkM2ZiNGM3YjMyY2NkNTcwYThiOWJiOGNiYmUyNTkyMTRhYjdkZTI1YSJ9fX19fQ=="); + let raw_tx = String::from("eyJzaWduYXR1cmUiOm51bGwsImZ1bmN0aW9uIjp7IkV0aGVyZXVtIjp7IlRyYW5zYWN0Ijp7IkxlZ2FjeSI6eyJub25jZSI6IjB4MCIsImdhc19wcmljZSI6IjB4MjU0MGJlNDAwIiwiZ2FzX2xpbWl0IjoiMHgxMDAwMDAiLCJhY3Rpb24iOnsiQ2FsbCI6IjB4MzMyNWE3ODQyNWYxN2E3ZTQ4N2ViNTY2NmIyYmZkOTNhYmIwNmM3MCJ9LCJ2YWx1ZSI6IjB4YSIsImlucHV0IjpbXSwic2lnbmF0dXJlIjp7InYiOjQzNDAsInIiOiIweDZiMjBjNzIzNTEzOTk4ZThmYTQ4NWM1MmI4ZjlhZTRmZDdiMWUwYmQwZGZiNzk4NTIzMThiMGMxMDBlOTFmNWUiLCJzIjoiMHg0ZDRjOGMxZjJlMTdjMDJjNGE4OTZlMjYyMTI3YjhiZDZlYmZkNWY1YTc1NWEzZTkyMjBjZmM2OGI4YzY5ZDVkIn19fX19fQ=="); let tx_bytes = base64::decode_config(raw_tx, base64::URL_SAFE).unwrap(); - let unchecked_tx: UncheckedTransaction<()> = + let unchecked_tx: UncheckedTransaction2<()> = serde_json::from_slice(tx_bytes.as_slice()).unwrap(); - if let Action::Ethereum(EthAction::Transact(tx)) = unchecked_tx.function { + if let Action2::Ethereum(EthAction2::Transact(tx)) = unchecked_tx.function { + let tx: LegacyTransaction = new_tx2legcay_tx(tx).unwrap(); let hash = H256::from_slice(Keccak256::digest(&rlp::encode(&tx)).as_slice()); assert_eq!( format!("{:?}", hash), - "0x0eeb0ff455b1b57b821634cf853e7247e584a675610f13097cc49c2022505df3" + "0x83901d025accca27ee53fdf1ee354f4437418731e0995ee031beb99499405d26" ); } else { panic!() diff --git a/src/components/contracts/rpc/src/eth.rs b/src/components/contracts/rpc/src/eth.rs index 5f572cb1b..106af6fea 100644 --- a/src/components/contracts/rpc/src/eth.rs +++ b/src/components/contracts/rpc/src/eth.rs @@ -8,7 +8,7 @@ use baseapp::{extensions::SignedExtra, BaseApp}; use config::abci::global_cfg::CFG; use ethereum::{ BlockV0 as EthereumBlock, LegacyTransactionMessage as EthereumTransactionMessage, - TransactionV0 as EthereumTransaction, + TransactionSignature, TransactionV0 as EthereumTransaction, }; use ethereum_types::{BigEndianHash, Bloom, H160, H256, H512, H64, U256, U64}; use evm::{ExitError, ExitReason}; @@ -228,6 +228,37 @@ impl EthApi for EthApiImpl { fn send_transaction(&self, request: TransactionRequest) -> BoxFuture> { debug!(target: "eth_rpc", "send_transaction, request:{:?}", request); + let mut request = request; + let curr_height = match self.block_number() { + Ok(h) => h.as_u64(), + Err(e) => return Box::pin(future::err(e)), + }; + let min_gas_price = + ::FeeCalculator::min_gas_price(curr_height); + + let min_gas_price_eip1559 = + ::FeeCalculator::min_gas_price(0); + + if request.gas_price.is_none() + && request.max_fee_per_gas.is_some() + && request.max_priority_fee_per_gas.is_some() + { + if CFG.checkpoint.enable_eip1559_height > curr_height { + return Box::pin(future::err(internal_err(format!( + "eip1559 not enabled at height: {:?}", + curr_height + )))); + } + + if request.max_fee_per_gas.unwrap() < min_gas_price { + return Box::pin(future::err(internal_err( + "eip1559 transaction max_fee_per_gas less than min_gas_price", + ))); + } + + request.gas_price = Some(min_gas_price_eip1559); + } + let from = match request.from { Some(from) => from, None => { @@ -260,18 +291,9 @@ impl EthApi for EthApiImpl { Err(e) => return Box::pin(future::err(e)), }; - let curr_height = match self.block_number() { - Ok(h) => h.as_u64(), - Err(e) => return Box::pin(future::err(e)), - }; - let message = EthereumTransactionMessage { nonce, - gas_price: request.gas_price.unwrap_or_else(|| { - ::FeeCalculator::min_gas_price( - curr_height, - ) - }), + gas_price: request.gas_price.unwrap_or(min_gas_price), gas_limit: request.gas.unwrap_or_else(U256::max_value), value: request.value.unwrap_or_else(U256::zero), input: request.data.map(|s| s.into_vec()).unwrap_or_default(), @@ -345,6 +367,40 @@ impl EthApi for EthApiImpl { ) -> BoxFuture> { debug!(target: "eth_rpc", "call, request:{:?}", request); + let mut request = request; + let curr_height = match self.block_number() { + Ok(v) => v, + Err(e) => { + return Box::pin(async move { Err(e) }); + } + } + .as_u64(); + + let min_gas_price = + ::FeeCalculator::min_gas_price(curr_height); + let min_gas_price_eip1559 = + ::FeeCalculator::min_gas_price(0); + + if request.gas_price.is_none() + && request.max_fee_per_gas.is_some() + && request.max_priority_fee_per_gas.is_some() + { + if CFG.checkpoint.enable_eip1559_height > curr_height { + return Box::pin(future::err(internal_err(format!( + "eip1559 not enabled at height: {:?}", + curr_height + )))); + } + + if request.max_fee_per_gas.unwrap() < min_gas_price { + return Box::pin(future::err(internal_err( + "eip1559 transaction max_fee_per_gas less than min_gas_price", + ))); + } + + request.gas_price = Some(min_gas_price_eip1559); + } + let account_base_app = self.account_base_app.clone(); let task = spawn_blocking(move || -> Result { @@ -352,6 +408,8 @@ impl EthApi for EthApiImpl { from, to, gas_price, + max_fee_per_gas: _max_fee_per_gas, + max_priority_fee_per_gas: _max_priority_fee_per_gas, gas, value, data, @@ -717,13 +775,94 @@ impl EthApi for EthApiImpl { } fn send_raw_transaction(&self, bytes: Bytes) -> BoxFuture> { - let transaction = match rlp::decode::(&bytes.0[..]) { - Ok(transaction) => transaction, - Err(_) => { - return Box::pin(future::err(internal_err("decode transaction failed"))); + let slice = &bytes.0[..]; + if slice.is_empty() { + return Box::pin(future::err(internal_err("transaction data is empty"))); + } + // let first = slice.get(0).unwrap(); + let first = slice.first().unwrap(); + let curr_height = match self.block_number() { + Ok(h) => h.as_u64(), + Err(e) => return Box::pin(future::err(e)), + }; + let min_gas_price = + ::FeeCalculator::min_gas_price(curr_height); + let min_gas_price_eip1559 = + ::FeeCalculator::min_gas_price(0); + + let transaction = if first > &0x7f { + // Legacy transaction. Decode and wrap in envelope. + match rlp::decode::(slice) { + Ok(transaction) => ethereum::TransactionV2::Legacy(transaction), + Err(_) => { + return Box::pin(future::err(internal_err( + "decode transaction failed", + ))); + } + } + } else { + if CFG.checkpoint.enable_eip1559_height > curr_height { + return Box::pin(future::err(internal_err(format!( + "eip1559 not enabled at height: {:?}", + curr_height + )))); + } + // Typed Transaction. + // `ethereum` crate decode implementation for `TransactionV2` expects a valid rlp input, + // and EIP-1559 breaks that assumption by prepending a version byte. + // We re-encode the payload input to get a valid rlp, and the decode implementation will strip + // them to check the transaction version byte. + let extend = rlp::encode(&slice); + match rlp::decode::(&extend[..]) { + Ok(transaction) => transaction, + Err(_) => { + return Box::pin(future::err(internal_err( + "decode transaction failed", + ))) + } + } + }; + + let transaction: ethereum::TransactionV0 = match transaction { + ethereum::TransactionV2::Legacy(tx) => tx, + ethereum::TransactionV2::EIP1559(tx) => { + if tx.max_fee_per_gas < min_gas_price { + return Box::pin(future::err(internal_err( + "eip1559 transaction max_fee_per_gas less than min_gas_price", + ))); + } + + let chain_id: u64 = ::ChainId::get(); + let v: u64 = if tx.odd_y_parity { + chain_id * 2 + 36 + } else { + chain_id * 2 + 35 + }; + let signature = match TransactionSignature::new(v, tx.r, tx.s) { + Some(sig) => sig, + None => { + return Box::pin(future::err(internal_err( + "eip1559 signature input error!!", + ))) + } + }; + + ethereum::TransactionV0 { + nonce: tx.nonce, + gas_price: min_gas_price_eip1559, + gas_limit: tx.gas_limit, + action: tx.action, + value: tx.value, + input: tx.input, + signature, + } + } + _ => { + return Box::pin(future::err(internal_err( + "do't support other transaction format!!!", + ))) } }; - debug!(target: "eth_rpc", "send_raw_transaction :{:?}", transaction); let transaction_hash = H256::from_slice(Keccak256::digest(&rlp::encode(&transaction)).as_slice()); @@ -764,6 +903,39 @@ impl EthApi for EthApiImpl { ) -> BoxFuture> { debug!(target: "eth_rpc", "estimate_gas, block number {:?} request:{:?}", number, request); + let mut request = request; + let curr_height = match self.block_number() { + Ok(v) => v, + Err(e) => { + return Box::pin(async move { Err(e) }); + } + } + .as_u64(); + let min_gas_price = + ::FeeCalculator::min_gas_price(curr_height); + let min_gas_price_eip1559 = + ::FeeCalculator::min_gas_price(0); + + if request.gas_price.is_none() + && request.max_fee_per_gas.is_some() + && request.max_priority_fee_per_gas.is_some() + { + if CFG.checkpoint.enable_eip1559_height > curr_height { + return Box::pin(future::err(internal_err(format!( + "eip1559 not enabled at height: {:?}", + curr_height + )))); + } + + if request.max_fee_per_gas.unwrap() < min_gas_price { + return Box::pin(future::err(internal_err( + "eip1559 transaction max_fee_per_gas less than min_gas_price", + ))); + } + + request.gas_price = Some(min_gas_price_eip1559); + } + let account_base_app = self.account_base_app.clone(); let task = spawn_blocking(move || { @@ -861,6 +1033,8 @@ impl EthApi for EthApiImpl { from, to, gas_price, + max_fee_per_gas: _max_fee_per_gas, + max_priority_fee_per_gas: _max_priority_fee_per_gas, gas, value, data, @@ -1139,6 +1313,8 @@ impl EthApi for EthApiImpl { ); let receipt = receipts[index].clone(); let status = statuses[index].clone(); + let transaction = block.transactions[index].clone(); + let mut cumulative_receipts = receipts; cumulative_receipts .truncate((status.transaction_index + 1) as usize); @@ -1196,6 +1372,7 @@ impl EthApi for EthApiImpl { status_code: Some(U64::from(receipt.state_root.to_low_u64_be())), logs_bloom: receipt.logs_bloom, state_root: None, + effective_gas_price: transaction.gas_price, })); } _ => Ok(None), @@ -1403,6 +1580,7 @@ fn rich_block_build( } }, size: Some(U256::from(rlp::encode(&block).len() as u32)), + base_fee_per_gas: None, }, extra_info: BTreeMap::new(), } @@ -1455,7 +1633,9 @@ fn transaction_build( |status| status.to, ), value: transaction.value, - gas_price: transaction.gas_price, + gas_price: Some(transaction.gas_price), + max_fee_per_gas: None, + max_priority_fee_per_gas: None, gas: transaction.gas_limit, input: Bytes(transaction.clone().input), creates: status.as_ref().and_then(|status| status.contract_address), @@ -1466,6 +1646,7 @@ fn transaction_build( v: U256::from(transaction.signature.v()), r: U256::from(transaction.signature.r().as_bytes()), s: U256::from(transaction.signature.s().as_bytes()), + access_list: None, } } @@ -1661,6 +1842,7 @@ fn dummy_block(height: u64, full: bool) -> Rich { uncles: vec![], transactions, size: Some(U256::from(0x1_u32)), + base_fee_per_gas: None, }; Rich { From edfa4ea07a9a9a9e50f084ffe78ecf15d4c72fd9 Mon Sep 17 00:00:00 2001 From: HarryLiIsMe <42673017+HarryLiIsMe@users.noreply.github.com> Date: Tue, 31 Jan 2023 10:16:04 +0800 Subject: [PATCH 04/10] fix lint error (#800) Co-authored-by: harry --- .../abciapp/src/abci/server/callback/mod.rs | 4 +- .../abciapp/src/abci/server/tx_sender.rs | 2 +- .../src/api/query_server/query_api/mod.rs | 2 +- .../api/submission_server/submission_api.rs | 2 +- src/components/abciapp/src/bins/findorad.rs | 6 +- src/components/config/src/abci/mod.rs | 10 +- src/components/contracts/baseapp/src/app.rs | 18 +- src/components/contracts/baseapp/src/lib.rs | 6 +- .../contracts/baseapp/src/modules.rs | 2 +- .../contracts/modules/account/src/impls.rs | 2 +- .../contracts/modules/account/src/tests.rs | 4 +- .../contracts/modules/ethereum/src/impls.rs | 4 +- .../contracts/modules/ethereum/src/lib.rs | 3 +- .../modules/ethereum/tests/ethereum_db.rs | 4 +- .../ethereum/tests/ethereum_integration.rs | 2 +- .../modules/evm/precompile/frc20/src/lib.rs | 8 +- .../evm/precompile/sha3fips/src/lib.rs | 8 +- .../modules/evm/precompile/utils/src/tests.rs | 2 +- .../contracts/modules/evm/src/precompile.rs | 8 +- .../modules/evm/tests/evm_integration.rs | 14 +- .../modules/evm/tests/utils/solidity.rs | 4 +- .../contracts/primitives/evm/src/lib.rs | 2 +- .../contracts/primitives/mocks/src/lib.rs | 2 +- .../rpc-core/src/types/block_number.rs | 11 +- .../primitives/rpc-core/src/types/bytes.rs | 2 +- .../primitives/rpc-core/src/types/filter.rs | 2 +- .../primitives/rpc-core/src/types/index.rs | 4 +- .../primitives/rpc-core/src/types/pubsub.rs | 2 +- .../contracts/primitives/storage/src/tests.rs | 2 +- .../contracts/primitives/utils/src/ecdsa.rs | 11 +- .../contracts/primitives/wasm/src/wasm.rs | 16 +- src/components/contracts/rpc/src/eth.rs | 43 ++--- .../contracts/rpc/src/eth_filter.rs | 12 +- src/components/contracts/rpc/src/lib.rs | 6 +- src/components/contracts/rpc/src/utils.rs | 4 +- .../finutils/src/bins/cfg_generator.rs | 3 +- src/components/finutils/src/bins/fn.rs | 10 +- .../finutils/src/bins/stt/init/i_testing.rs | 2 +- .../finutils/src/bins/stt/init/mod.rs | 2 +- src/components/finutils/src/bins/stt/stt.rs | 8 +- .../finutils/src/common/ddev/init.rs | 6 +- .../finutils/src/common/ddev/mod.rs | 2 +- src/components/finutils/src/common/dev/mod.rs | 2 +- src/components/finutils/src/common/mod.rs | 33 ++-- src/components/finutils/src/common/utils.rs | 2 +- .../finutils/src/txn_builder/mod.rs | 7 +- src/ledger/src/data_model/mod.rs | 7 +- src/ledger/src/data_model/test.rs | 2 +- src/ledger/src/staking/cosig.rs | 2 +- src/ledger/src/staking/mod.rs | 5 +- src/ledger/src/store/api_cache.rs | 54 +++--- src/ledger/src/store/helpers.rs | 2 +- src/ledger/src/store/mod.rs | 9 +- src/libs/bitmap/src/lib.rs | 13 +- src/libs/bitmap/src/test.rs | 20 +-- src/libs/globutils/src/lib.rs | 4 +- src/libs/globutils/src/logging.rs | 6 +- src/libs/merkle_tree/src/lib.rs | 159 ++++++++---------- src/libs/sliding_set/src/lib.rs | 5 +- src/libs/sparse_merkle_tree/src/lib.rs | 4 +- 60 files changed, 278 insertions(+), 325 deletions(-) diff --git a/src/components/abciapp/src/abci/server/callback/mod.rs b/src/components/abciapp/src/abci/server/callback/mod.rs index 3d32493c2..8dacc1830 100644 --- a/src/components/abciapp/src/abci/server/callback/mod.rs +++ b/src/components/abciapp/src/abci/server/callback/mod.rs @@ -277,11 +277,11 @@ pub fn deliver_tx( if let Err(err) = s.account_base_app.write().deliver_findora_tx(&txn, &hash.0) { - tracing::error!(target: "abciapp", "deliver convert account tx failed: {:?}", err); + tracing::error!(target: "abciapp", "deliver convert account tx failed: {err:?}", ); resp.code = 1; resp.log = - format!("deliver convert account tx failed: {:?}", err); + format!("deliver convert account tx failed: {err:?}",); return resp; } diff --git a/src/components/abciapp/src/abci/server/tx_sender.rs b/src/components/abciapp/src/abci/server/tx_sender.rs index 13dbb354a..0382234e6 100644 --- a/src/components/abciapp/src/abci/server/tx_sender.rs +++ b/src/components/abciapp/src/abci/server/tx_sender.rs @@ -50,7 +50,7 @@ pub fn forward_txn_with_mode( ) }; - let tendermint_reply = format!("http://{}", url); + let tendermint_reply = format!("http://{url}",); if 2000 > TX_PENDING_CNT.fetch_add(1, Ordering::Relaxed) { POOL.spawn_ok(async move { ruc::info_omit!(attohttpc::post(&tendermint_reply) diff --git a/src/components/abciapp/src/api/query_server/query_api/mod.rs b/src/components/abciapp/src/api/query_server/query_api/mod.rs index e799d2cb9..617f4d247 100644 --- a/src/components/abciapp/src/api/query_server/query_api/mod.rs +++ b/src/components/abciapp/src/api/query_server/query_api/mod.rs @@ -803,7 +803,7 @@ impl QueryApi { }); for (host, port) in addrs.iter() { - hdr = hdr.bind(&format!("{}:{}", host, port)).c(d!())? + hdr = hdr.bind(&format!("{host}:{port}")).c(d!())? } hdr.run(); diff --git a/src/components/abciapp/src/api/submission_server/submission_api.rs b/src/components/abciapp/src/api/submission_server/submission_api.rs index bc8b690f2..4c67684b3 100644 --- a/src/components/abciapp/src/api/submission_server/submission_api.rs +++ b/src/components/abciapp/src/api/submission_server/submission_api.rs @@ -130,7 +130,7 @@ impl SubmissionApi { web::get().to(txn_status::), ) }) - .bind(&format!("{}:{}", host, port)) + .bind(&format!("{host}:{port}",)) .c(d!())? .run(); diff --git a/src/components/abciapp/src/bins/findorad.rs b/src/components/abciapp/src/bins/findorad.rs index a9eaee0ab..cf450af88 100644 --- a/src/components/abciapp/src/bins/findorad.rs +++ b/src/components/abciapp/src/bins/findorad.rs @@ -123,10 +123,10 @@ fn node_command() -> Result<()> { ctrlc::set_handler(move || { //info_omit!(kill(Pid::from_raw(0), Signal::SIGINT)); pnk!(abcid_child.kill().c(d!())); - pnk!(abcid_child.wait().c(d!()).map(|s| println!("{}", s))); + pnk!(abcid_child.wait().c(d!()).map(|s| println!("{s}",))); pnk!(tendermint_child.kill()); - pnk!(tendermint_child.wait().c(d!()).map(|s| println!("{}", s))); + pnk!(tendermint_child.wait().c(d!()).map(|s| println!("{s}",))); pnk!(send.send(())); }) @@ -163,7 +163,7 @@ fn init_command() -> Result<()> { fn pack() -> Result<()> { let bin_path_orig = get_bin_path().c(d!())?; let bin_name = bin_path_orig.file_name().c(d!())?.to_str().c(d!())?; - let bin_path = format!("/tmp/{}", bin_name); + let bin_path = format!("/tmp/{bin_name}",); fs::copy(bin_path_orig, &bin_path).c(d!())?; let mut f = OpenOptions::new().append(true).open(bin_path).c(d!())?; diff --git a/src/components/config/src/abci/mod.rs b/src/components/config/src/abci/mod.rs index f20193426..9816f6d99 100644 --- a/src/components/config/src/abci/mod.rs +++ b/src/components/config/src/abci/mod.rs @@ -165,11 +165,11 @@ impl CheckPointConfig { return Some(config); } Err(error) => { - panic!("failed to create file: {:?}", error) + panic!("failed to create file: {error:?}",) } }; } else { - panic!("failed to open file: {:?}", error) + panic!("failed to open file: {error:?}",) } } }; @@ -455,7 +455,7 @@ pub mod global_cfg { .value_of("checkpoint-file") .map(|v| v.to_owned()) .unwrap_or_else(|| String::from("./checkpoint.toml")); - println!("{}", checkpoint_path); + println!("{checkpoint_path}",); let res = Config { abci_host: ah, @@ -562,7 +562,7 @@ pub mod global_cfg { .into_iter() .rev() .for_each(|h| { - println!(" {}", h); + println!(" {h}",); }); exit(0); } @@ -580,7 +580,7 @@ pub mod global_cfg { || m.is_present("snapshot-rollback-to") || m.is_present("snapshot-rollback-to-exact") { - println!("\x1b[31;01m\n{}\x1b[00m", HINTS); + println!("\x1b[31;01m\n{HINTS}\x1b[00m",); let (h, strict) = m .value_of("snapshot-rollback-to-exact") diff --git a/src/components/contracts/baseapp/src/app.rs b/src/components/contracts/baseapp/src/app.rs index 2211728ce..5928bddbe 100644 --- a/src/components/contracts/baseapp/src/app.rs +++ b/src/components/contracts/baseapp/src/app.rs @@ -50,7 +50,7 @@ impl crate::BaseApp { let ctx = self.create_query_context(Some(req.height as u64), req.prove); if let Err(e) = ctx { - return err_resp(format!("Cannot create query context with err: {}!", e)); + return err_resp(format!("Cannot create query context with err: {e}!",)); } match path.remove(0) { @@ -144,14 +144,14 @@ impl crate::BaseApp { } resp.code = ar.code; if ar.code != 0 { - info!(target: "baseapp", "Transaction check error, action result {:?}", ar); + info!(target: "baseapp", "Transaction check error, action result {ar:?}", ); resp.log = ar.log; } } Err(e) => { - info!(target: "baseapp", "Transaction check error: {}", e); + info!(target: "baseapp", "Transaction check error: {e}", ); resp.code = 1; - resp.log = format!("Transaction check error: {}", e); + resp.log = format!("Transaction check error: {e}",); } } }; @@ -294,9 +294,9 @@ impl crate::BaseApp { resp } Err(e) => { - error!(target: "baseapp", "Ethereum transaction deliver error: {}", e); + error!(target: "baseapp", "Ethereum transaction deliver error: {e}", ); resp.code = 1; - resp.log = format!("Ethereum transaction deliver error: {}", e); + resp.log = format!("Ethereum transaction deliver error: {e}",); resp } } @@ -334,8 +334,8 @@ impl crate::BaseApp { .write() .commit(block_height) .unwrap_or_else(|e| { - println!("{:?}", e); - panic!("Failed to commit chain state at height: {}", block_height) + println!("{e:?}",); + panic!("Failed to commit chain state at height: {block_height}",) }); // Commit module data based on root_hash @@ -347,7 +347,7 @@ impl crate::BaseApp { .write() .commit(block_height) .unwrap_or_else(|_| { - panic!("Failed to commit chain db at height: {}", block_height) + panic!("Failed to commit chain db at height: {block_height}",) }); // Reset the deliver state, but keep the ethereum cache diff --git a/src/components/contracts/baseapp/src/lib.rs b/src/components/contracts/baseapp/src/lib.rs index 02de696a1..f58a41134 100644 --- a/src/components/contracts/baseapp/src/lib.rs +++ b/src/components/contracts/baseapp/src/lib.rs @@ -310,7 +310,7 @@ impl BaseApp { } fn validate_height(&self, height: i64) -> Result<()> { - ensure!(height >= 1, format!("invalid height: {}", height)); + ensure!(height >= 1, format!("invalid height: {height}",)); let mut expected_height = self.chain_state.read().height().unwrap_or_default() as i64; if expected_height == 0 { @@ -320,7 +320,7 @@ impl BaseApp { } ensure!( height == expected_height, - format!("invalid height: {}; expected: {}", height, expected_height) + format!("invalid height: {height}; expected: {expected_height}") ); Ok(()) } @@ -386,7 +386,7 @@ impl BaseProvider for BaseApp { fn account_of(&self, who: &Address, height: Option) -> Result { let ctx = self.create_query_context(height, false)?; module_account::App::::account_of(&ctx, who, height) - .ok_or(eg!(format!("account does not exist: {}", who))) + .ok_or(eg!(format!("account does not exist: {who}",))) } fn current_block(&self, id: Option) -> Option { diff --git a/src/components/contracts/baseapp/src/modules.rs b/src/components/contracts/baseapp/src/modules.rs index c84a21925..123db0093 100644 --- a/src/components/contracts/baseapp/src/modules.rs +++ b/src/components/contracts/baseapp/src/modules.rs @@ -60,7 +60,7 @@ impl ModuleManager { self.template_module.query_route(ctx, path, req) } else { resp.code = 1; - resp.log = format!("Invalid query module route: {}!", module_name); + resp.log = format!("Invalid query module route: {module_name}!",); resp } } diff --git a/src/components/contracts/modules/account/src/impls.rs b/src/components/contracts/modules/account/src/impls.rs index c0ff983cf..c4c64eb13 100644 --- a/src/components/contracts/modules/account/src/impls.rs +++ b/src/components/contracts/modules/account/src/impls.rs @@ -138,7 +138,7 @@ impl AccountAsset
for App { } let mut target_account = Self::account_of(ctx, target, None) - .c(d!(format!("account: {} does not exist", target)))?; + .c(d!(format!("account: {target} does not exist",)))?; target_account.balance = target_account .balance .checked_sub(balance) diff --git a/src/components/contracts/modules/account/src/tests.rs b/src/components/contracts/modules/account/src/tests.rs index 7d20c8733..36c8c3322 100644 --- a/src/components/contracts/modules/account/src/tests.rs +++ b/src/components/contracts/modules/account/src/tests.rs @@ -19,7 +19,7 @@ fn setup() -> Context { .unwrap() .as_nanos(); let mut path = temp_dir(); - path.push(format!("temp-findora-db–{}", time)); + path.push(format!("temp-findora-db–{time}",)); let fdb = FinDB::open(path).unwrap(); let chain_state = Arc::new(RwLock::new(ChainState::new( @@ -29,7 +29,7 @@ fn setup() -> Context { ))); let mut rocks_path = temp_dir(); - rocks_path.push(format!("temp-rocks-db–{}", time)); + rocks_path.push(format!("temp-rocks-db–{time}",)); let rdb = RocksDB::open(rocks_path).unwrap(); let chain_db = Arc::new(RwLock::new(ChainState::new( diff --git a/src/components/contracts/modules/ethereum/src/impls.rs b/src/components/contracts/modules/ethereum/src/impls.rs index 61654416b..639098b04 100644 --- a/src/components/contracts/modules/ethereum/src/impls.rs +++ b/src/components/contracts/modules/ethereum/src/impls.rs @@ -268,7 +268,7 @@ impl App { return Ok(ActionResult { code: 1, data: vec![], - log: format!("{}", e), + log: format!("{e}",), gas_wanted: gas_limit.low_u64(), gas_used: 0, events, @@ -343,7 +343,7 @@ impl App { let message_len = data[36..68].iter().sum::(); let body: &[u8] = &data[68..68 + message_len as usize]; if let Ok(reason) = std::str::from_utf8(body) { - message = format!("{} {}", message, reason); + message = format!("{message} {reason}"); } } (3, message) diff --git a/src/components/contracts/modules/ethereum/src/lib.rs b/src/components/contracts/modules/ethereum/src/lib.rs index 07c180354..f32905238 100644 --- a/src/components/contracts/modules/ethereum/src/lib.rs +++ b/src/components/contracts/modules/ethereum/src/lib.rs @@ -228,8 +228,7 @@ impl ValidateUnsigned for App { let total_payment = transaction.value.saturating_add(fee); if balance < total_payment { return Err(eg!(format!( - "InsufficientBalance, origin: {:?}, actual balance {}, but expected payment {}", - origin, balance, total_payment + "InsufficientBalance, origin: {origin:?}, actual balance {balance}, but expected payment {total_payment}", ))); } diff --git a/src/components/contracts/modules/ethereum/tests/ethereum_db.rs b/src/components/contracts/modules/ethereum/tests/ethereum_db.rs index 1551e9a2f..039159e9a 100644 --- a/src/components/contracts/modules/ethereum/tests/ethereum_db.rs +++ b/src/components/contracts/modules/ethereum/tests/ethereum_db.rs @@ -18,7 +18,7 @@ fn setup() -> Context { .unwrap() .as_nanos(); let mut path = temp_dir(); - path.push(format!("temp-findora-db–{}", time)); + path.push(format!("temp-findora-db–{time}",)); let fdb = FinDB::open(path).unwrap(); let chain_state = Arc::new(RwLock::new(ChainState::new( @@ -28,7 +28,7 @@ fn setup() -> Context { ))); let mut rocks_path = temp_dir(); - rocks_path.push(format!("temp-rocks-db–{}", time)); + rocks_path.push(format!("temp-rocks-db–{time}",)); let rdb = RocksDB::open(rocks_path).unwrap(); let chain_db = Arc::new(RwLock::new(ChainState::new( diff --git a/src/components/contracts/modules/ethereum/tests/ethereum_integration.rs b/src/components/contracts/modules/ethereum/tests/ethereum_integration.rs index 2332c04e7..2fbc24384 100644 --- a/src/components/contracts/modules/ethereum/tests/ethereum_integration.rs +++ b/src/components/contracts/modules/ethereum/tests/ethereum_integration.rs @@ -114,7 +114,7 @@ fn test_abci_deliver_tx() { resp.code, resp.log ); - println!("transfer resp: {:?}", resp); + println!("transfer resp: {resp:?}",); // initial balance = 100_0000_0000_0000_0000_u64, gas limit = 21000, transfer balance = 10 assert_eq!( diff --git a/src/components/contracts/modules/evm/precompile/frc20/src/lib.rs b/src/components/contracts/modules/evm/precompile/frc20/src/lib.rs index 21a6fa2e3..2b083636e 100644 --- a/src/components/contracts/modules/evm/precompile/frc20/src/lib.rs +++ b/src/components/contracts/modules/evm/precompile/frc20/src/lib.rs @@ -304,7 +304,7 @@ impl FRC20 { ); C::AccountAsset::approve(state, &caller, &spender_id, amount) - .map_err(|e| error(format!("{:?}", e)))?; + .map_err(|e| error(format!("{e:?}",)))?; Ok(PrecompileOutput { exit_status: ExitSucceed::Returned, @@ -349,7 +349,7 @@ impl FRC20 { ); C::AccountAsset::transfer(state, &caller, &recipient_id, amount) - .map_err(|e| error(format!("{:?}", e)))?; + .map_err(|e| error(format!("{e:?}",)))?; Ok(PrecompileOutput { exit_status: ExitSucceed::Returned, @@ -405,7 +405,7 @@ impl FRC20 { ); C::AccountAsset::transfer(state, &from_id, &recipient_id, amount) - .map_err(|e| error(format!("{:?}", e)))?; + .map_err(|e| error(format!("{e:?}",)))?; C::AccountAsset::approve( state, @@ -413,7 +413,7 @@ impl FRC20 { &caller, allowance.saturating_sub(amount), ) - .map_err(|e| error(format!("{:?}", e)))?; + .map_err(|e| error(format!("{e:?}",)))?; Ok(PrecompileOutput { exit_status: ExitSucceed::Returned, diff --git a/src/components/contracts/modules/evm/precompile/sha3fips/src/lib.rs b/src/components/contracts/modules/evm/precompile/sha3fips/src/lib.rs index 55d5e5493..8718f50d1 100644 --- a/src/components/contracts/modules/evm/precompile/sha3fips/src/lib.rs +++ b/src/components/contracts/modules/evm/precompile/sha3fips/src/lib.rs @@ -89,7 +89,7 @@ mod tests { Ok(()) } Err(e) => { - panic!("Test not expected to fail: {:?}", e); + panic!("Test not expected to fail: {e:?}",); } } } @@ -110,7 +110,7 @@ mod tests { Ok(()) } Err(e) => { - panic!("Test not expected to fail: {:?}", e); + panic!("Test not expected to fail: {e:?}",); } } } @@ -131,7 +131,7 @@ mod tests { Ok(()) } Err(e) => { - panic!("Test not expected to fail: {:?}", e); + panic!("Test not expected to fail: {e:?}",); } } } @@ -154,7 +154,7 @@ mod tests { Ok(()) } Err(e) => { - panic!("Test not expected to fail: {:?}", e); + panic!("Test not expected to fail: {e:?}",); } } } diff --git a/src/components/contracts/modules/evm/precompile/utils/src/tests.rs b/src/components/contracts/modules/evm/precompile/utils/src/tests.rs index f00e0e2c7..6ac27929f 100644 --- a/src/components/contracts/modules/evm/precompile/utils/src/tests.rs +++ b/src/components/contracts/modules/evm/precompile/utils/src/tests.rs @@ -379,7 +379,7 @@ fn write_address_nested_array() { writer_output .chunks_exact(32) .map(H256::from_slice) - .for_each(|hash| println!("{:?}", hash)); + .for_each(|hash| println!("{hash:?}",)); // We can read this "manualy" using simpler functions since arrays are 32-byte aligned. let mut reader = EvmDataReader::new(&writer_output); diff --git a/src/components/contracts/modules/evm/src/precompile.rs b/src/components/contracts/modules/evm/src/precompile.rs index 828a067be..54e8b8229 100644 --- a/src/components/contracts/modules/evm/src/precompile.rs +++ b/src/components/contracts/modules/evm/src/precompile.rs @@ -17,12 +17,12 @@ pub trait PrecompileSet { /// Otherwise, calculate the amount of gas needed with given `input` and /// `target_gas`. Return `Some(Ok(status, output, gas_used))` if the execution /// is successful. Otherwise return `Some(Err(_))`. - fn execute<'context, 'vicinity, 'config, T>( + fn execute( address: H160, input: &[u8], target_gas: Option, context: &Context, - state: &mut FindoraStackState<'context, 'vicinity, 'config, T>, + state: &mut FindoraStackState<'_, '_, '_, T>, is_static: bool, ) -> Option; } @@ -53,12 +53,12 @@ pub trait PrecompileId { impl PrecompileSet for Tuple { for_tuples!( where #( Tuple: Precompile + PrecompileId )* ); - fn execute<'context, 'vicinity, 'config, T>( + fn execute( address: H160, input: &[u8], target_gas: Option, context: &Context, - state: &mut FindoraStackState<'context, 'vicinity, 'config, T>, + state: &mut FindoraStackState<'_, '_, '_, T>, _is_static: bool, ) -> Option { for_tuples!( #( diff --git a/src/components/contracts/modules/evm/tests/evm_integration.rs b/src/components/contracts/modules/evm/tests/evm_integration.rs index 7f6163ce2..24e4fc188 100644 --- a/src/components/contracts/modules/evm/tests/evm_integration.rs +++ b/src/components/contracts/modules/evm/tests/evm_integration.rs @@ -131,7 +131,7 @@ fn test_deploy_deliver_tx() -> (H160, ethabi::Contract) { resp.code, resp.log ); - println!("deploy erc20 result: {:?}\n", resp); + println!("deploy erc20 result: {resp:?}\n",); let info = serde_json::from_slice::(&resp.data).unwrap(); if let CallOrCreateInfo::Create(info) = info { @@ -144,7 +144,7 @@ fn test_deploy_deliver_tx() -> (H160, ethabi::Contract) { println!("erc20 contract address: {:?}\n", info.value); (info.value, contract_abi) } else { - panic!("not expected result: {:?}", info) + panic!("not expected result: {info:?}",) } } @@ -197,7 +197,7 @@ fn test_mint_deliver_tx(contract: ERC20) { resp.code, resp.log ); - println!("call erc20 mint result: {:?}\n", resp); + println!("call erc20 mint result: {resp:?}\n",); } fn test_transfer_check_tx(contract: ERC20) { @@ -239,7 +239,7 @@ fn test_transfer_deliver_tx(contract: ERC20) { resp.code, resp.log ); - println!("call erc20 transfer result: {:?}\n", resp); + println!("call erc20 transfer result: {resp:?}\n",); } fn test_balance_of_deliver_tx(contract: ERC20, who: H160) -> U256 { @@ -255,7 +255,7 @@ fn test_balance_of_deliver_tx(contract: ERC20, who: H160) -> U256 { resp.code, resp.log ); - println!("call erc20 balanceOf result: {:?}\n", resp); + println!("call erc20 balanceOf result: {resp:?}\n",); let info = serde_json::from_slice::(&resp.data).unwrap(); if let CallOrCreateInfo::Call(info) = info { @@ -267,7 +267,7 @@ fn test_balance_of_deliver_tx(contract: ERC20, who: H160) -> U256 { U256::from_big_endian(info.value.as_ref()) } else { - panic!("not expected result: {:?}", info) + panic!("not expected result: {info:?}",) } } @@ -297,7 +297,7 @@ fn test_balance_of_with_eth_call(contract: ERC20, who: H160) -> U256 { ) .unwrap(); - println!("eth call erc20 balanceOf result: {:?}\n", info); + println!("eth call erc20 balanceOf result: {info:?}\n",); U256::from_big_endian(info.value.as_ref()) } diff --git a/src/components/contracts/modules/evm/tests/utils/solidity.rs b/src/components/contracts/modules/evm/tests/utils/solidity.rs index 6fda0f06f..64728b4ca 100644 --- a/src/components/contracts/modules/evm/tests/utils/solidity.rs +++ b/src/components/contracts/modules/evm/tests/utils/solidity.rs @@ -28,8 +28,8 @@ impl ContractConstructor { P2: AsRef, P3: AsRef, { - let bin_file = format!("{}.bin", contract_name); - let abi_file = format!("{}.abi", contract_name); + let bin_file = format!("{contract_name}.bin",); + let abi_file = format!("{contract_name}.abi",); let hex_path = artifacts_base_path.as_ref().join(bin_file); let hex_rep = match std::fs::read_to_string(&hex_path) { Ok(hex) => hex, diff --git a/src/components/contracts/primitives/evm/src/lib.rs b/src/components/contracts/primitives/evm/src/lib.rs index 2b972ea60..172c098a7 100644 --- a/src/components/contracts/primitives/evm/src/lib.rs +++ b/src/components/contracts/primitives/evm/src/lib.rs @@ -79,6 +79,6 @@ impl BlockId { impl core::fmt::Display for BlockId { fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - write!(f, "{:?}", self) + write!(f, "{self:?}",) } } diff --git a/src/components/contracts/primitives/mocks/src/lib.rs b/src/components/contracts/primitives/mocks/src/lib.rs index f88cac008..e34b7fdd1 100644 --- a/src/components/contracts/primitives/mocks/src/lib.rs +++ b/src/components/contracts/primitives/mocks/src/lib.rs @@ -79,7 +79,7 @@ pub fn create_temp_db_path() -> PathBuf { .unwrap() .as_nanos(); let mut path = temp_dir(); - path.push(format!("temp-findora-db–{}", time)); + path.push(format!("temp-findora-db–{time}",)); path } diff --git a/src/components/contracts/primitives/rpc-core/src/types/block_number.rs b/src/components/contracts/primitives/rpc-core/src/types/block_number.rs index c94fc31a8..9a2523bb1 100644 --- a/src/components/contracts/primitives/rpc-core/src/types/block_number.rs +++ b/src/components/contracts/primitives/rpc-core/src/types/block_number.rs @@ -76,10 +76,9 @@ impl Serialize for BlockNumber { hash, require_canonical, } => serializer.serialize_str(&format!( - "{{ 'hash': '{}', 'requireCanonical': '{}' }}", - hash, require_canonical + "{{ 'hash': '{hash}', 'requireCanonical': '{require_canonical}' }}", )), - BlockNumber::Num(ref x) => serializer.serialize_str(&format!("0x{:x}", x)), + BlockNumber::Num(ref x) => serializer.serialize_str(&format!("0x{x:x}",)), BlockNumber::Latest => serializer.serialize_str("latest"), BlockNumber::Earliest => serializer.serialize_str("earliest"), BlockNumber::Pending => serializer.serialize_str("pending"), @@ -116,7 +115,7 @@ impl<'a> Visitor<'a> for BlockNumberVisitor { "pending" => Ok(BlockNumber::Pending), _ if value.starts_with("0x") => u64::from_str_radix(&value[2..], 16) .map(BlockNumber::Num) - .map_err(|e| Error::custom(format!("Invalid block number: {}", e))), + .map_err(|e| Error::custom(format!("Invalid block number: {e}",))), _ => value.parse::().map(BlockNumber::Num).map_err(|_| { Error::custom( "Invalid block number: non-decimal or missing 0x prefix".to_string(), @@ -148,7 +147,7 @@ impl<'a> Visitor<'a> for BlockNumberVisitor { let value: String = visitor.next_value()?; if let Some(v) = value.strip_prefix("0x") { let number = u64::from_str_radix(v, 16).map_err(|e| { - Error::custom(format!("Invalid block number: {}", e)) + Error::custom(format!("Invalid block number: {e}",)) })?; block_number = Some(number); @@ -165,7 +164,7 @@ impl<'a> Visitor<'a> for BlockNumberVisitor { "requireCanonical" => { require_canonical = visitor.next_value()?; } - key => return Err(Error::custom(format!("Unknown key: {}", key))), + key => return Err(Error::custom(format!("Unknown key: {key}",))), }, None => break, }; diff --git a/src/components/contracts/primitives/rpc-core/src/types/bytes.rs b/src/components/contracts/primitives/rpc-core/src/types/bytes.rs index 4aae0b7c3..d330ee5f5 100644 --- a/src/components/contracts/primitives/rpc-core/src/types/bytes.rs +++ b/src/components/contracts/primitives/rpc-core/src/types/bytes.rs @@ -85,7 +85,7 @@ impl<'a> Visitor<'a> for BytesVisitor { { if value.len() >= 2 && value.starts_with("0x") && value.len() & 1 == 0 { Ok(Bytes::new(FromHex::from_hex(&value[2..]).map_err(|e| { - Error::custom(format!("Invalid hex: {}", e)) + Error::custom(format!("Invalid hex: {e}",)) })?)) } else { Err(Error::custom( diff --git a/src/components/contracts/primitives/rpc-core/src/types/filter.rs b/src/components/contracts/primitives/rpc-core/src/types/filter.rs index c3d3b2221..2b800e540 100644 --- a/src/components/contracts/primitives/rpc-core/src/types/filter.rs +++ b/src/components/contracts/primitives/rpc-core/src/types/filter.rs @@ -59,7 +59,7 @@ where .map(VariadicValue::Single) .or_else(|_| from_value(v).map(VariadicValue::Multiple)) .map_err(|err| { - D::Error::custom(format!("Invalid variadic value type: {}", err)) + D::Error::custom(format!("Invalid variadic value type: {err}",)) }) } } diff --git a/src/components/contracts/primitives/rpc-core/src/types/index.rs b/src/components/contracts/primitives/rpc-core/src/types/index.rs index 30fcf63cb..a3cd28552 100644 --- a/src/components/contracts/primitives/rpc-core/src/types/index.rs +++ b/src/components/contracts/primitives/rpc-core/src/types/index.rs @@ -56,11 +56,11 @@ impl<'a> Visitor<'a> for IndexVisitor { match value { _ if value.starts_with("0x") => usize::from_str_radix(&value[2..], 16) .map(Index) - .map_err(|e| Error::custom(format!("Invalid index: {}", e))), + .map_err(|e| Error::custom(format!("Invalid index: {e}",))), _ => value .parse::() .map(Index) - .map_err(|e| Error::custom(format!("Invalid index: {}", e))), + .map_err(|e| Error::custom(format!("Invalid index: {e}",))), } } diff --git a/src/components/contracts/primitives/rpc-core/src/types/pubsub.rs b/src/components/contracts/primitives/rpc-core/src/types/pubsub.rs index c9c7b5c1e..2b28359d3 100644 --- a/src/components/contracts/primitives/rpc-core/src/types/pubsub.rs +++ b/src/components/contracts/primitives/rpc-core/src/types/pubsub.rs @@ -105,7 +105,7 @@ impl<'a> Deserialize<'a> for Params { from_value(v) .map(Params::Logs) - .map_err(|e| D::Error::custom(format!("Invalid Pub-Sub parameters: {}", e))) + .map_err(|e| D::Error::custom(format!("Invalid Pub-Sub parameters: {e}",))) } } diff --git a/src/components/contracts/primitives/storage/src/tests.rs b/src/components/contracts/primitives/storage/src/tests.rs index b67602afa..b8e031abe 100644 --- a/src/components/contracts/primitives/storage/src/tests.rs +++ b/src/components/contracts/primitives/storage/src/tests.rs @@ -12,7 +12,7 @@ fn setup_temp_db() -> Arc>> { .unwrap() .as_nanos(); let mut path = temp_dir(); - path.push(format!("temp-findora-db–{}", time)); + path.push(format!("temp-findora-db–{time}",)); let fdb = TempFinDB::open(path).unwrap(); let chain_state = Arc::new(RwLock::new(ChainState::new( fdb, diff --git a/src/components/contracts/primitives/utils/src/ecdsa.rs b/src/components/contracts/primitives/utils/src/ecdsa.rs index 4e71af624..6bbf4fecd 100644 --- a/src/components/contracts/primitives/utils/src/ecdsa.rs +++ b/src/components/contracts/primitives/utils/src/ecdsa.rs @@ -73,9 +73,8 @@ impl<'de> Deserialize<'de> for Public { { let pk = base64::decode_config(String::deserialize(deserializer)?, base64::URL_SAFE) - .map_err(|e| de::Error::custom(format!("{:?}", e)))?; - Public::try_from(pk.as_slice()) - .map_err(|e| de::Error::custom(format!("{:?}", e))) + .map_err(|e| de::Error::custom(format!("{e:?}",)))?; + Public::try_from(pk.as_slice()).map_err(|e| de::Error::custom(format!("{e:?}",))) } } @@ -174,9 +173,9 @@ impl<'de> Deserialize<'de> for Signature { D: Deserializer<'de>, { let signature_hex = hex::decode(String::deserialize(deserializer)?) - .map_err(|e| de::Error::custom(format!("{:?}", e)))?; + .map_err(|e| de::Error::custom(format!("{e:?}",)))?; Signature::try_from(signature_hex.as_ref()) - .map_err(|e| de::Error::custom(format!("{:?}", e))) + .map_err(|e| de::Error::custom(format!("{e:?}",))) } } @@ -444,7 +443,7 @@ mod test { "2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee00000000000000000200d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a4500000000000000" ); let signature = pair.sign(&message[..]); - println!("Correct signature: {:?}", signature); + println!("Correct signature: {signature:?}",); assert!(SecpPair::verify(&signature, &message[..], &public)); assert!(!SecpPair::verify(&signature, "Other message", &public)); } diff --git a/src/components/contracts/primitives/wasm/src/wasm.rs b/src/components/contracts/primitives/wasm/src/wasm.rs index ac75067dd..da4632e7e 100644 --- a/src/components/contracts/primitives/wasm/src/wasm.rs +++ b/src/components/contracts/primitives/wasm/src/wasm.rs @@ -2,16 +2,14 @@ use core::fmt::Display; use ethereum::{ - LegacyTransactionMessage,TransactionSignature, - TransactionV0 as LegacyTransaction, TransactionV2, + LegacyTransactionMessage, TransactionSignature, TransactionV0 as LegacyTransaction, + TransactionV2, }; use ethereum_types::{H160, H256}; use fp_types::{ - actions::{ - ethereum::Action2 as EthAction2, Action2, - }, - assemble::{UncheckedTransaction2}, + actions::{ethereum::Action2 as EthAction2, Action2}, + assemble::UncheckedTransaction2, crypto::secp256k1_ecdsa_recover, }; use fp_utils::tx::EvmRawTxWrapper; @@ -60,7 +58,7 @@ pub fn recover_tx_signer(raw_tx: String) -> Result { None => return Err(error_to_jsvalue("invalid raw tx")), }; let signer = recover_signer(&tx).c(d!()).map_err(error_to_jsvalue)?; - Ok(format!("{:?}", signer)) + Ok(format!("{signer:?}",)) } else { Err(error_to_jsvalue("invalid raw tx")) } @@ -84,7 +82,7 @@ pub fn evm_tx_hash(raw_tx: String) -> Result { None => return Err(error_to_jsvalue("invalid raw tx")), }; let hash = H256::from_slice(Keccak256::digest(&rlp::encode(&tx)).as_slice()); - Ok(format!("{:?}", hash)) + Ok(format!("{hash:?}",)) } else { Err(error_to_jsvalue("invalid raw tx")) } @@ -133,7 +131,7 @@ mod test { let raw_tx = String::from("eyJzaWduYXR1cmUiOm51bGwsImZ1bmN0aW9uIjp7IkV0aGVyZXVtIjp7IlRyYW5zYWN0Ijp7IkxlZ2FjeSI6eyJub25jZSI6IjB4MCIsImdhc19wcmljZSI6IjB4MjU0MGJlNDAwIiwiZ2FzX2xpbWl0IjoiMHgxMDAwMDAiLCJhY3Rpb24iOnsiQ2FsbCI6IjB4MzMyNWE3ODQyNWYxN2E3ZTQ4N2ViNTY2NmIyYmZkOTNhYmIwNmM3MCJ9LCJ2YWx1ZSI6IjB4YSIsImlucHV0IjpbXSwic2lnbmF0dXJlIjp7InYiOjQzNDAsInIiOiIweDZiMjBjNzIzNTEzOTk4ZThmYTQ4NWM1MmI4ZjlhZTRmZDdiMWUwYmQwZGZiNzk4NTIzMThiMGMxMDBlOTFmNWUiLCJzIjoiMHg0ZDRjOGMxZjJlMTdjMDJjNGE4OTZlMjYyMTI3YjhiZDZlYmZkNWY1YTc1NWEzZTkyMjBjZmM2OGI4YzY5ZDVkIn19fX19fQ=="); let tx_bytes = base64::decode_config(raw_tx, base64::URL_SAFE).unwrap(); let unchecked_tx: UncheckedTransaction2<()> = - serde_json::from_slice(tx_bytes.as_slice()).unwrap(); + serde_json::from_slice(tx_bytes.as_slice()).unwrap(); if let Action2::Ethereum(EthAction2::Transact(tx)) = unchecked_tx.function { let tx: LegacyTransaction = new_tx2legcay_tx(tx).unwrap(); let signer = recover_signer(&tx).unwrap(); diff --git a/src/components/contracts/rpc/src/eth.rs b/src/components/contracts/rpc/src/eth.rs index 106af6fea..22beb8cbd 100644 --- a/src/components/contracts/rpc/src/eth.rs +++ b/src/components/contracts/rpc/src/eth.rs @@ -103,8 +103,7 @@ impl EthApiImpl { Some(block) => Some(block.header.number.as_u64()), None => { return Err(internal_err(format!( - "block number not found, hash: {:?}", - hash + "block number not found, hash: {hash:?}", ))) } }, @@ -113,8 +112,7 @@ impl EthApiImpl { Some(num) } else { return Err(internal_err(format!( - "block number: {} exceeds version range: {:?}", - num, range + "block number: {num} exceeds version range: {range:?}", ))); } } @@ -245,8 +243,7 @@ impl EthApi for EthApiImpl { { if CFG.checkpoint.enable_eip1559_height > curr_height { return Box::pin(future::err(internal_err(format!( - "eip1559 not enabled at height: {:?}", - curr_height + "eip1559 not enabled at height: {curr_height:?}", )))); } @@ -387,8 +384,7 @@ impl EthApi for EthApiImpl { { if CFG.checkpoint.enable_eip1559_height > curr_height { return Box::pin(future::err(internal_err(format!( - "eip1559 not enabled at height: {:?}", - curr_height + "eip1559 not enabled at height: {curr_height:?}", )))); } @@ -437,7 +433,7 @@ impl EthApi for EthApiImpl { .read() .create_query_context(None, false) .map_err(|err| { - internal_err(format!("create query context error: {:?}", err)) + internal_err(format!("create query context error: {err:?}",)) })?; if let Some(block) = block { ctx.header @@ -464,9 +460,9 @@ impl EthApi for EthApiImpl { &ctx, call, &config, ) .map_err(|err| { - internal_err(format!("evm runner call error: {:?}", err)) + internal_err(format!("evm runner call error: {err:?}",)) })?; - debug!(target: "eth_rpc", "evm runner call result: {:?}", info); + debug!(target: "eth_rpc", "evm runner call result: {info:?}", ); error_on_execution_failure(&info.exit_reason, &info.value)?; @@ -486,9 +482,9 @@ impl EthApi for EthApiImpl { &ctx, create, &config, ) .map_err(|err| { - internal_err(format!("evm runner create error: {:?}", err)) + internal_err(format!("evm runner create error: {err:?}",)) })?; - debug!(target: "eth_rpc", "evm runner create result: {:?}", info); + debug!(target: "eth_rpc", "evm runner create result: {info:?}", ); error_on_execution_failure(&info.exit_reason, &[])?; @@ -803,8 +799,7 @@ impl EthApi for EthApiImpl { } else { if CFG.checkpoint.enable_eip1559_height > curr_height { return Box::pin(future::err(internal_err(format!( - "eip1559 not enabled at height: {:?}", - curr_height + "eip1559 not enabled at height: {curr_height:?}", )))); } // Typed Transaction. @@ -922,8 +917,7 @@ impl EthApi for EthApiImpl { { if CFG.checkpoint.enable_eip1559_height > curr_height { return Box::pin(future::err(internal_err(format!( - "eip1559 not enabled at height: {:?}", - curr_height + "eip1559 not enabled at height: {curr_height:?}", )))); } @@ -946,8 +940,7 @@ impl EthApi for EthApiImpl { (Some(BlockId::Number(U256::from(num))), false) } else { return Err(internal_err(format!( - "block number: {} exceeds version range: {:?}", - num, range + "block number: {num} exceeds version range: {range:?}", ))); } } @@ -1026,7 +1019,7 @@ impl EthApi for EthApiImpl { .read() .create_query_context(if pending { None } else { Some(0) }, false) .map_err(|err| { - internal_err(format!("create query context error: {:?}", err)) + internal_err(format!("create query context error: {err:?}",)) })?; let CallRequest { @@ -1065,9 +1058,9 @@ impl EthApi for EthApiImpl { &ctx, call, &config, ) .map_err(|err| { - internal_err(format!("evm runner call error: {:?}", err)) + internal_err(format!("evm runner call error: {err:?}",)) })?; - debug!(target: "eth_rpc", "evm runner call result: {:?}", info); + debug!(target: "eth_rpc", "evm runner call result: {info:?}", ); Ok(ExecuteResult { data: info.value, @@ -1089,9 +1082,9 @@ impl EthApi for EthApiImpl { &ctx, create, &config, ) .map_err(|err| { - internal_err(format!("evm runner create error: {:?}", err)) + internal_err(format!("evm runner create error: {err:?}",)) })?; - debug!(target: "eth_rpc", "evm runner create result: {:?}", info); + debug!(target: "eth_rpc", "evm runner create result: {info:?}", ); Ok(ExecuteResult { data: vec![], @@ -1160,7 +1153,7 @@ impl EthApi for EthApiImpl { id = Some(BlockId::Number(number)); index = idx as usize } - println!("{:?}, {:?}", id, index); + println!("{id:?}, {index:?}"); let block = account_base_app.read().current_block(id.clone()); let statuses = account_base_app diff --git a/src/components/contracts/rpc/src/eth_filter.rs b/src/components/contracts/rpc/src/eth_filter.rs index 18c71814d..eb82a4228 100644 --- a/src/components/contracts/rpc/src/eth_filter.rs +++ b/src/components/contracts/rpc/src/eth_filter.rs @@ -154,8 +154,7 @@ impl EthFilterApiImpl { // Check for restrictions if ret.len() as u32 > max_past_logs { return Err(internal_err(format!( - "query returned more than {} results", - max_past_logs + "query returned more than {max_past_logs} results", ))); } if begin_request.elapsed() > max_duration { @@ -302,7 +301,7 @@ impl EthFilterApi for EthFilterApiImpl { _ => Err(internal_err("Method not available.")), } } else { - Err(internal_err(format!("Filter id {:?} does not exist.", key))) + Err(internal_err(format!("Filter id {key:?} does not exist.",))) } } else { Err(internal_err("Filter pool is not available.")) @@ -346,12 +345,11 @@ impl EthFilterApi for EthFilterApiImpl { Ok(ret) } _ => Err(internal_err(format!( - "Filter id {:?} is not a Log filter.", - key + "Filter id {key:?} is not a Log filter.", ))), } } else { - Err(internal_err(format!("Filter id {:?} does not exist.", key))) + Err(internal_err(format!("Filter id {key:?} does not exist.",))) } } else { Err(internal_err("Filter pool is not available.")) @@ -367,7 +365,7 @@ impl EthFilterApi for EthFilterApiImpl { if locked.remove(&key).is_some() { Ok(true) } else { - Err(internal_err(format!("Filter id {:?} does not exist.", key))) + Err(internal_err(format!("Filter id {key:?} does not exist.",))) } } else { Err(internal_err("Filter pool is not available.")) diff --git a/src/components/contracts/rpc/src/lib.rs b/src/components/contracts/rpc/src/lib.rs index d989d77bf..51c482bb7 100644 --- a/src/components/contracts/rpc/src/lib.rs +++ b/src/components/contracts/rpc/src/lib.rs @@ -161,7 +161,7 @@ pub fn error_on_execution_failure( } Err(Error { code: ErrorCode::InternalError, - message: format!("evm error: {:?}", e), + message: format!("evm error: {e:?}",), data: Some(Value::String("0x".to_string())), }) } @@ -174,7 +174,7 @@ pub fn error_on_execution_failure( let message_len = data[36..68].iter().sum::(); let body: &[u8] = &data[68..68 + message_len as usize]; if let Ok(reason) = std::str::from_utf8(body) { - message = format!("{} {}", message, reason); + message = format!("{message} {reason}"); } } Err(Error { @@ -185,7 +185,7 @@ pub fn error_on_execution_failure( } ExitReason::Fatal(e) => Err(Error { code: ErrorCode::InternalError, - message: format!("evm fatal: {:?}", e), + message: format!("evm fatal: {e:?}"), data: Some(Value::String("0x".to_string())), }), } diff --git a/src/components/contracts/rpc/src/utils.rs b/src/components/contracts/rpc/src/utils.rs index 51745ebdb..865f0021e 100644 --- a/src/components/contracts/rpc/src/utils.rs +++ b/src/components/contracts/rpc/src/utils.rs @@ -6,7 +6,7 @@ use tokio::task::JoinError; pub fn convert_join_error_to_rpc_error(e: JoinError) -> Error { Error { code: ErrorCode::InternalError, - message: format!("{:?}", e), + message: format!("{e:?}",), data: None, } } @@ -14,7 +14,7 @@ pub fn convert_join_error_to_rpc_error(e: JoinError) -> Error { pub fn convert_error_to_rpc_error(e: impl Debug) -> Error { Error { code: ErrorCode::InternalError, - message: format!("{:?}", e), + message: format!("{e:?}",), data: None, } } diff --git a/src/components/finutils/src/bins/cfg_generator.rs b/src/components/finutils/src/bins/cfg_generator.rs index d41b09914..66bb1a0b5 100644 --- a/src/components/finutils/src/bins/cfg_generator.rs +++ b/src/components/finutils/src/bins/cfg_generator.rs @@ -76,8 +76,7 @@ fn gen() -> Result<()> { .and_then(|m| fs::write(&secret_info_path, m).c(d!())) .map(|_| { println!( - "\x1b[01mSecret info has been writed to \x1b[31m{}\x1b[00m", - secret_info_path + "\x1b[01mSecret info has been writed to \x1b[31m{secret_info_path}\x1b[00m", ); }) } diff --git a/src/components/finutils/src/bins/fn.rs b/src/components/finutils/src/bins/fn.rs index f8823e74b..75240bbe3 100644 --- a/src/components/finutils/src/bins/fn.rs +++ b/src/components/finutils/src/bins/fn.rs @@ -209,7 +209,7 @@ fn run() -> Result<()> { .c(d!())?; } else { let help = "fn asset [--create | --issue | --show]"; - println!("{}", help); + println!("{help}",); } } else if let Some(m) = matches.subcommand_matches("staker-update") { let vm = if let Some(memo) = m.value_of("validator-memo") { @@ -431,7 +431,7 @@ fn run() -> Result<()> { } if address.is_some() { let (account, info) = contract_account_info(address, is_address_fra)?; - println!("AccountId: {}\n{:#?}\n", account, info); + println!("AccountId: {account}\n{info:#?}\n",); } } else if let Some(m) = matches.subcommand_matches("contract-deposit") { let amount = m.value_of("amount").c(d!())?; @@ -542,7 +542,7 @@ fn run() -> Result<()> { if let Some(path) = m.value_of("file-path") { serde_json::to_writer_pretty(&File::create(path).c(d!())?, &keys).c(d!())?; - println!("Keys saved to file: {}", path); + println!("Keys saved to file: {path}",); } // print keys to terminal @@ -603,7 +603,7 @@ fn run() -> Result<()> { ); // Print UTXO table - println!("Owned utxos for {:?}", pk); + println!("Owned utxos for {pk:?}",); println!("{:-^1$}", "", 100); println!( "{0: <8} | {1: <18} | {2: <45} ", @@ -1132,7 +1132,7 @@ fn tip_fail(e: impl fmt::Display) { eprintln!( "\x1b[35;01mTips\x1b[01m:\n\tPlease send your error messages to us,\n\tif you can't understand their meanings ~^!^~\x1b[00m" ); - eprintln!("\n{}", e); + eprintln!("\n{e}",); } fn tip_success() { diff --git a/src/components/finutils/src/bins/stt/init/i_testing.rs b/src/components/finutils/src/bins/stt/init/i_testing.rs index 909fdc10a..271e655e3 100644 --- a/src/components/finutils/src/bins/stt/init/i_testing.rs +++ b/src/components/finutils/src/bins/stt/init/i_testing.rs @@ -394,7 +394,7 @@ struct TmValidator { } fn get_26657_validators(sa: &str) -> Result { - let url = format!("{}:26657/validators", sa); + let url = format!("{sa}:26657/validators",); attohttpc::get(url) .send() .c(d!())? diff --git a/src/components/finutils/src/bins/stt/init/mod.rs b/src/components/finutils/src/bins/stt/init/mod.rs index 7de620bce..d0721d999 100644 --- a/src/components/finutils/src/bins/stt/init/mod.rs +++ b/src/components/finutils/src/bins/stt/init/mod.rs @@ -40,7 +40,7 @@ pub fn init( } else { let root_kp = wallet::restore_keypair_from_mnemonic_default(ROOT_MNEMONIC).c(d!())?; - println!(">>> Block interval: {} seconds", interval); + println!(">>> Block interval: {interval} seconds",); println!(">>> Define and issue FRA ..."); common::utils::send_tx(&fra_gen_initial_tx(&root_kp)).c(d!())?; diff --git a/src/components/finutils/src/bins/stt/stt.rs b/src/components/finutils/src/bins/stt/stt.rs index 7f416affe..d757d8084 100644 --- a/src/components/finutils/src/bins/stt/stt.rs +++ b/src/components/finutils/src/bins/stt/stt.rs @@ -406,20 +406,20 @@ fn print_info( if show_user_list { let user_list = serde_json::to_string_pretty(&*USER_LIST).c(d!())?; - println!("\x1b[31;01mUSER LIST:\x1b[00m\n{}\n", user_list); + println!("\x1b[31;01mUSER LIST:\x1b[00m\n{user_list}\n",); } if show_validator_list { let validator_list = serde_json::to_string_pretty(&*VALIDATOR_LIST).c(d!())?; - println!("\x1b[31;01mVALIDATOR LIST:\x1b[00m\n{}\n", validator_list); + println!("\x1b[31;01mVALIDATOR LIST:\x1b[00m\n{validator_list}\n",); } if let Some(u) = user { let balance = get_balance(u).c(d!())?; - println!("\x1b[31;01mUSER BALANCE:\x1b[00m\n{} FRA units\n", balance); + println!("\x1b[31;01mUSER BALANCE:\x1b[00m\n{balance} FRA units\n",); let user_info = get_delegation_info(u).c(d!())?; - println!("\x1b[31;01mUSER DELEGATION:\x1b[00m\n{}\n", user_info); + println!("\x1b[31;01mUSER DELEGATION:\x1b[00m\n{user_info}\n",); } Ok(()) diff --git a/src/components/finutils/src/common/ddev/init.rs b/src/components/finutils/src/common/ddev/init.rs index 29419fd70..93c7f631e 100644 --- a/src/components/finutils/src/common/ddev/init.rs +++ b/src/components/finutils/src/common/ddev/init.rs @@ -48,7 +48,7 @@ pub(super) fn init(env: &mut Env) -> Result<()> { let port = ports[IDX_TM_RPC]; let page_size = env.custom_data.initial_validator_num; let tmrpc_endpoint = - format!("http://{}:{}/validators?per_page={}", addr, port, page_size); + format!("http://{addr}:{port}/validators?per_page={page_size}",); let tm_validators = attohttpc::get(&tmrpc_endpoint) .send() @@ -173,7 +173,7 @@ fn setup_initial_validators(env: &Env) -> Result<()> { fn send_tx(env: &Env, tx: &Transaction) -> Result<()> { let (addr, ports) = env.get_addrports_any_node(); let port = ports[IDX_APP_8669]; - let rpc_endpoint = format!("http://{}:{}/submit_transaction", addr, port); + let rpc_endpoint = format!("http://{addr}:{port}/submit_transaction"); attohttpc::post(&rpc_endpoint) .header(attohttpc::header::CONTENT_TYPE, "application/json") .bytes(&serde_json::to_vec(tx).c(d!())?) @@ -244,7 +244,7 @@ fn new_tx_builder(env: &Env) -> Result { fn gen_8668_endpoint(env: &Env) -> String { let (addr, ports) = env.get_addrports_any_node(); let port = ports[IDX_APP_8668]; - format!("http://{}:{}", addr, port) + format!("http://{addr}:{port}",) } #[derive(Debug, Clone, Deserialize, Serialize)] diff --git a/src/components/finutils/src/common/ddev/mod.rs b/src/components/finutils/src/common/ddev/mod.rs index 26a8421e5..a71e67b8e 100644 --- a/src/components/finutils/src/common/ddev/mod.rs +++ b/src/components/finutils/src/common/ddev/mod.rs @@ -304,7 +304,7 @@ impl NodeOptsGenerator, EnvMeta>> for OptsGe ); if let Some(cp) = m.custom_data.checkpoint_file.as_ref() { - write!(opts, " --checkpoint-file {}", cp).unwrap(); + write!(opts, " --checkpoint-file {cp}",).unwrap(); } write!(opts, " {}", &m.app_extra_opts).unwrap(); diff --git a/src/components/finutils/src/common/dev/mod.rs b/src/components/finutils/src/common/dev/mod.rs index 926d0aaf7..0692e7b2e 100644 --- a/src/components/finutils/src/common/dev/mod.rs +++ b/src/components/finutils/src/common/dev/mod.rs @@ -182,7 +182,7 @@ impl NodeOptsGenerator, EnvMeta>> for OptsGe ); if let Some(cp) = m.custom_data.checkpoint_file.as_ref() { - write!(opts, " --checkpoint-file {}", cp).unwrap(); + write!(opts, " --checkpoint-file {cp}",).unwrap(); } write!(opts, " {}", &m.app_extra_opts).unwrap(); diff --git a/src/components/finutils/src/common/mod.rs b/src/components/finutils/src/common/mod.rs index 1f9e848fa..7486d02f2 100644 --- a/src/components/finutils/src/common/mod.rs +++ b/src/components/finutils/src/common/mod.rs @@ -155,8 +155,7 @@ pub fn stake( || diff!(network_height, local_height) > 3 { println!( - "The difference in block height of your node and the remote network is too big: \n remote / local: {} / {}", - network_height, local_height + "The difference in block height of your node and the remote network is too big: \n remote / local: {network_height} / {local_height}", ); if !force { println!("Append option --force to ignore this warning."); @@ -329,7 +328,7 @@ pub fn show(basic: bool, is_address_fra: bool) -> Result<()> { let kp = get_keypair(is_address_fra).c(d!())?; let serv_addr = ruc::info!(get_serv_addr()).map(|i| { - println!("\x1b[31;01mServer URL:\x1b[00m\n{}\n", i); + println!("\x1b[31;01mServer URL:\x1b[00m\n{i}\n",); }); let xfr_account = ruc::info!(get_keypair(is_address_fra)).map(|i| { @@ -348,7 +347,7 @@ pub fn show(basic: bool, is_address_fra: bool) -> Result<()> { }); let self_balance = ruc::info!(utils::get_balance(&kp)).map(|i| { - println!("\x1b[31;01mNode Balance:\x1b[00m\n{} FRA units\n", i); + println!("\x1b[31;01mNode Balance:\x1b[00m\n{i} FRA units\n",); }); if basic { @@ -357,7 +356,7 @@ pub fn show(basic: bool, is_address_fra: bool) -> Result<()> { let td_info = ruc::info!(get_td_pubkey()).map(|i| { let addr = td_pubkey_to_td_addr(&i); - println!("\x1b[31;01mValidator Node Addr:\x1b[00m\n{}\n", addr); + println!("\x1b[31;01mValidator Node Addr:\x1b[00m\n{addr}\n",); (i, addr) }); @@ -371,7 +370,7 @@ pub fn show(basic: bool, is_address_fra: bool) -> Result<()> { serde_json::to_string_pretty(&di).c(d!("server returned invalid data")) }); let delegation_info = ruc::info!(delegation_info).map(|i| { - println!("\x1b[31;01mYour Delegation:\x1b[00m\n{}\n", i); + println!("\x1b[31;01mYour Delegation:\x1b[00m\n{i}\n",); }); if let Ok((tpk, addr)) = td_info.as_ref() { @@ -385,7 +384,7 @@ pub fn show(basic: bool, is_address_fra: bool) -> Result<()> { .c(d!("server returned invalid data")) }) .map(|i| { - println!("\x1b[31;01mYour Staking:\x1b[00m\n{}\n", i); + println!("\x1b[31;01mYour Staking:\x1b[00m\n{i}\n",); }); ruc::info_omit!(res); } @@ -639,8 +638,7 @@ pub fn gen_key(is_fra_address: bool) -> (String, String, String, XfrKeyPair) { pub fn gen_key_and_print(is_fra_address: bool) { let (wallet_addr, mnemonic, key, _) = gen_key(is_fra_address); println!( - "\n\x1b[31;01mWallet Address:\x1b[00m {}\n\x1b[31;01mMnemonic:\x1b[00m {}\n\x1b[31;01mKey:\x1b[00m {}\n", - wallet_addr, mnemonic, key + "\n\x1b[31;01mWallet Address:\x1b[00m {wallet_addr}\n\x1b[31;01mMnemonic:\x1b[00m {mnemonic}\n\x1b[31;01mKey:\x1b[00m {key}\n", ); } @@ -649,7 +647,7 @@ fn restore_keypair_from_str_with_default( is_fra_address: bool, ) -> Result { if let Some(sk) = sk_str { - serde_json::from_str::(&format!("\"{}\"", sk)) + serde_json::from_str::(&format!("\"{sk}\"",)) .map(|sk| sk.into_keypair()) .c(d!("Invalid secret key")) } else { @@ -905,7 +903,7 @@ pub fn show_asset(addr: &str) -> Result<()> { for asset in assets { let base64 = asset.body.asset.code.to_base64(); let h = hex::encode(asset.body.asset.code.val.0); - println!("Base64: {}, Hex: {}", base64, h); + println!("Base64: {base64}, Hex: {h}",); } Ok(()) @@ -924,12 +922,11 @@ pub fn convert_bar2abar( ) -> Result { // parse sender XfrSecretKey or generate from Mnemonic setup with wallet let from = match owner_sk { - Some(str) => ruc::info!(serde_json::from_str::(&format!( - "\"{}\"", - str - ))) - .c(d!())? - .into_keypair(), + Some(str) => { + ruc::info!(serde_json::from_str::(&format!("\"{str}\"",))) + .c(d!())? + .into_keypair() + } None => get_keypair(is_address_fra).c(d!())?, }; // parse receiver AxfrPubKey @@ -1397,7 +1394,7 @@ pub fn get_owned_abars( axfr_secret_key: AXfrKeyPair, commitments_list: &str, ) -> Result<()> { - println!("Abar data for commitments: {}", commitments_list); + println!("Abar data for commitments: {commitments_list}",); println!(); println!( "{0: <8} | {1: <18} | {2: <45} | {3: <9} | {4: <45}", diff --git a/src/components/finutils/src/common/utils.rs b/src/components/finutils/src/common/utils.rs index ef89aae62..d6f346350 100644 --- a/src/components/finutils/src/common/utils.rs +++ b/src/components/finutils/src/common/utils.rs @@ -482,7 +482,7 @@ struct TmStatus { // retrieve tendermint status and node info #[inline(always)] fn get_network_status(addr: &str) -> Result { - let url = format!("{}:26657/status", addr); + let url = format!("{addr}:26657/status",); attohttpc::get(url) .send() diff --git a/src/components/finutils/src/txn_builder/mod.rs b/src/components/finutils/src/txn_builder/mod.rs index 102cba254..ad40f086e 100644 --- a/src/components/finutils/src/txn_builder/mod.rs +++ b/src/components/finutils/src/txn_builder/mod.rs @@ -799,7 +799,7 @@ impl TransactionBuilder { return Err(eg!("insufficient FRA to pay fees!")); } if fra_remainder > 0 { - println!("Transaction FRA Remainder Amount: {:?}", fra_remainder); + println!("Transaction FRA Remainder Amount: {fra_remainder:?}",); let oabar_money_back = OpenAnonAssetRecordBuilder::new() .amount(fra_remainder as u64) .asset_type(ASSET_TYPE_FRA) @@ -1353,7 +1353,7 @@ impl TransferOperationBuilder { .iter() .fold(0, |acc, ar| acc + ar.open_asset_record.amount); if input_total != output_total { - return Err(eg!(format!("{} != {}", input_total, output_total))); + return Err(eg!(format!("{input_total} != {output_total}",))); } Ok(()) @@ -1421,8 +1421,7 @@ impl TransferOperationBuilder { .fold(0, |acc, ar| acc + ar.open_asset_record.amount); if spend_total != output_total { return Err(eg!(format!( - "Spend total != output, {} != {}", - spend_total, output_total + "Spend total != output, {spend_total} != {output_total}", ))); } self.output_records.append(&mut partially_consumed_inputs); diff --git a/src/ledger/src/data_model/mod.rs b/src/ledger/src/data_model/mod.rs index a929225d5..0fe831488 100644 --- a/src/ledger/src/data_model/mod.rs +++ b/src/ledger/src/data_model/mod.rs @@ -254,10 +254,7 @@ impl AssetTypeCode { val: NoahAssetType(buf), }) } - Err(e) => Err(eg!((format!( - "Failed to deserialize base64 '{}': {}", - b64, e - )))), + Err(e) => Err(eg!((format!("Failed to deserialize base64 '{b64}': {e}",)))), } } @@ -1037,7 +1034,7 @@ impl AssetTypePrefix { AssetTypePrefix::NFT => "02", }; - hex::decode(format!("{:0>64}", code)).unwrap() + hex::decode(format!("{code:0>64}",)).unwrap() } } diff --git a/src/ledger/src/data_model/test.rs b/src/ledger/src/data_model/test.rs index 145fdadd1..8b0e1918d 100755 --- a/src/ledger/src/data_model/test.rs +++ b/src/ledger/src/data_model/test.rs @@ -46,7 +46,7 @@ fn test_gen_random_with_rng() { let uniform_stddev = 1.0 / (12.0f64).sqrt(); let average = sum as f64 / sample_size as f64; let stddev = (uniform_stddev * 255.0) / (sample_size as f64).sqrt(); - println!("Average {}, stddev {}", average, stddev); + println!("Average {average}, stddev {stddev}"); assert!(average > 127.5 - 5.0 * stddev); assert!(average < 127.5 + 5.0 * stddev); } diff --git a/src/ledger/src/staking/cosig.rs b/src/ledger/src/staking/cosig.rs index e88333307..041631f71 100644 --- a/src/ledger/src/staking/cosig.rs +++ b/src/ledger/src/staking/cosig.rs @@ -207,7 +207,7 @@ impl fmt::Display for CoSigErr { CoSigErr::WeightInsufficient => "total weight is lower than the threshold", CoSigErr::SigInvalid => "invalid signature", }; - write!(f, "{}", msg) + write!(f, "{msg}",) } } diff --git a/src/ledger/src/staking/mod.rs b/src/ledger/src/staking/mod.rs index 6d0545835..fca45ab10 100644 --- a/src/ledger/src/staking/mod.rs +++ b/src/ledger/src/staking/mod.rs @@ -1461,7 +1461,7 @@ impl Staking { vd.addr_td_to_app .get(addr) .copied() - .c(d!(format!("Failed to get pk {}", addr))) + .c(d!(format!("Failed to get pk {addr}",))) }) } @@ -2452,8 +2452,7 @@ pub fn check_delegation_amount(am: Amount, is_append: bool) -> Result<()> { Ok(()) } else { let msg = format!( - "Invalid delegation amount: {} (min: {}, max: {})", - am, lowb, MAX_DELEGATION_AMOUNT + "Invalid delegation amount: {am} (min: {lowb}, max: {MAX_DELEGATION_AMOUNT})", ); Err(eg!(msg)) } diff --git a/src/ledger/src/store/api_cache.rs b/src/ledger/src/store/api_cache.rs index a08f3c277..38bb290bc 100644 --- a/src/ledger/src/store/api_cache.rs +++ b/src/ledger/src/store/api_cache.rs @@ -92,55 +92,45 @@ impl ApiCache { ApiCache { prefix: prefix.to_owned(), related_transactions: new_mapx!(format!( - "api_cache/{}related_transactions", - prefix + "api_cache/{prefix}related_transactions", )), - related_transfers: new_mapx!(format!( - "api_cache/{}related_transfers", - prefix - )), - claim_hist_txns: new_mapx!(format!("api_cache/{}claim_hist_txns", prefix)), + related_transfers: new_mapx!( + format!("api_cache/{prefix}related_transfers",) + ), + claim_hist_txns: new_mapx!(format!("api_cache/{prefix}claim_hist_txns",)), coinbase_oper_hist: new_mapx!(format!( - "api_cache/{}coinbase_oper_hist", - prefix + "api_cache/{prefix}coinbase_oper_hist", )), - created_assets: new_mapx!(format!("api_cache/{}created_assets", prefix)), - issuances: new_mapx!(format!("api_cache/{}issuances", prefix)), + created_assets: new_mapx!(format!("api_cache/{prefix}created_assets",)), + issuances: new_mapx!(format!("api_cache/{prefix}issuances",)), token_code_issuances: new_mapx!(format!( - "api_cache/{}token_code_issuances", - prefix + "api_cache/{prefix}token_code_issuances", )), - owner_memos: new_mapxnk!(format!("api_cache/{}owner_memos", prefix)), - abar_memos: new_mapx!(format!("api_cache/{}abar_memos", prefix)), + owner_memos: new_mapxnk!(format!("api_cache/{prefix}owner_memos",)), + abar_memos: new_mapx!(format!("api_cache/{prefix}abar_memos",)), utxos_to_map_index: new_mapxnk!(format!( - "api_cache/{}utxos_to_map_index", - prefix + "api_cache/{prefix}utxos_to_map_index", )), - txo_to_txnid: new_mapxnk!(format!("api_cache/{}txo_to_txnid", prefix)), - atxo_to_txnid: new_mapx!(format!("api_cache/{}atxo_to_txnid", prefix)), - txn_sid_to_hash: new_mapxnk!(format!("api_cache/{}txn_sid_to_hash", prefix)), - txn_hash_to_sid: new_mapx!(format!("api_cache/{}txn_hash_to_sid", prefix)), + txo_to_txnid: new_mapxnk!(format!("api_cache/{prefix}txo_to_txnid",)), + atxo_to_txnid: new_mapx!(format!("api_cache/{prefix}atxo_to_txnid",)), + txn_sid_to_hash: new_mapxnk!(format!("api_cache/{prefix}txn_sid_to_hash",)), + txn_hash_to_sid: new_mapx!(format!("api_cache/{prefix}txn_hash_to_sid",)), staking_global_rate_hist: new_mapxnk!(format!( - "api_cache/{}staking_global_rate_hist", - prefix + "api_cache/{prefix}staking_global_rate_hist", )), height_to_max_atxo: new_mapxnk!(format!( - "api_cache/{}height_to_max_atxo", - prefix + "api_cache/{prefix}height_to_max_atxo", )), staking_self_delegation_hist: new_mapx!(format!( - "api_cache/{}staking_self_delegation_hist", - prefix + "api_cache/{prefix}staking_self_delegation_hist", )), staking_delegation_amount_hist: new_mapx!(format!( - "api_cache/{}staking_delegation_amount_hist", - prefix + "api_cache/{prefix}staking_delegation_amount_hist", )), staking_delegation_rwd_hist: new_mapx!(format!( - "api_cache/{}staking_delegation_rwd_hist", - prefix + "api_cache/{prefix}staking_delegation_rwd_hist", )), - last_sid: new_mapx!(format!("api_cache/{}last_sid", prefix)), + last_sid: new_mapx!(format!("api_cache/{prefix}last_sid",)), state_commitment_version: None, } } diff --git a/src/ledger/src/store/helpers.rs b/src/ledger/src/store/helpers.rs index 5acbc8097..b74d65475 100644 --- a/src/ledger/src/store/helpers.rs +++ b/src/ledger/src/store/helpers.rs @@ -103,7 +103,7 @@ pub fn apply_transaction( } Err(e) => { fn unwrap_failed(msg: &str, error: impl Debug) -> ! { - panic!("{}: {:?}", msg, error) + panic!("{msg}: {error:?}",) } unwrap_failed("apply_transaction: error in compute_effect", e) } diff --git a/src/ledger/src/store/mod.rs b/src/ledger/src/store/mod.rs index 6c2d42e20..75fb1a7ef 100644 --- a/src/ledger/src/store/mod.rs +++ b/src/ledger/src/store/mod.rs @@ -579,7 +579,7 @@ impl LedgerState { /// Initialize a new Ledger structure. pub fn new(basedir: &str, prefix: Option<&str>) -> Result { let prefix = if let Some(p) = prefix { - format!("{}_", p) + format!("{p}_",) } else { "".to_owned() }; @@ -1402,7 +1402,7 @@ impl LedgerStatus { /// Load or init LedgerStatus from snapshot #[inline(always)] pub fn new(basedir: &str, snapshot_file: &str) -> Result { - let path = format!("{}/{}", basedir, snapshot_file); + let path = format!("{basedir}/{snapshot_file}",); match fs::read_to_string(path) { Ok(s) => serde_json::from_str(&s).c(d!()), Err(e) => { @@ -1480,8 +1480,7 @@ impl LedgerStatus { // Check to see that this nrpt has not been seen before if self.sliding_set.has_key_at(seq_id as usize, rand) { return Err(eg!(format!( - "No replay token ({:?}, {})seen before at possible replay", - rand, seq_id + "No replay token ({rand:?}, {seq_id})seen before at possible replay", ))); } } @@ -1744,7 +1743,7 @@ impl LedgerStatus { no_replay_token.get_seq_id() as usize, ); if let Err(e) = self.sliding_set.insert(rand, seq_id) { - pd!(format!("Error inserting into window: {}", e)); + pd!(format!("Error inserting into window: {e}",)); } } block.no_replay_tokens.clear(); diff --git a/src/libs/bitmap/src/lib.rs b/src/libs/bitmap/src/lib.rs index fbf2bed15..a30a08527 100644 --- a/src/libs/bitmap/src/lib.rs +++ b/src/libs/bitmap/src/lib.rs @@ -293,8 +293,7 @@ impl BlockHeader { && block_contents != BIT_HEADER { return Err(eg!(format!( - "That content type ({}) is invalid.", - block_contents + "That content type ({block_contents}) is invalid.", ))); } @@ -671,10 +670,10 @@ impl BitMap { let file_size = file.seek(SeekFrom::End(0)).c(d!())?; if file_size % BLOCK_SIZE as u64 != 0 { - return Err(eg!(format!("That file size ({}) is invalid.", file_size))); + return Err(eg!(format!("That file size ({file_size}) is invalid.",))); } - file.seek(SeekFrom::Start(0)).c(d!())?; + file.rewind().c(d!())?; let total_blocks = file_size / BLOCK_SIZE as u64; // Reserve space in our vectors. @@ -737,11 +736,11 @@ impl BitMap { if validate_checksums { if let Err(e) = block.validate(BIT_ARRAY, i as u64) { - println!("Block {} failed validation: {}", i, e); + println!("Block {i} failed validation: {e}",); pass = false; } } else if let Err(e) = header.validate(BIT_ARRAY, i as u64) { - println!("Block {} failed validation: {}", i, e); + println!("Block {i} failed validation: {e}"); pass = false; } @@ -1254,7 +1253,7 @@ impl BitMap { let bytes_consumed = list_size as usize * INDEX_SIZE; if index + bytes_consumed > bytes.len() { - return Err(eg!(format!("An index list was too long: {}", list_size))); + return Err(eg!(format!("An index list was too long: {list_size}",))); } for _ in 0..list_size { diff --git a/src/libs/bitmap/src/test.rs b/src/libs/bitmap/src/test.rs index 58ff122d0..619aeb2be 100755 --- a/src/libs/bitmap/src/test.rs +++ b/src/libs/bitmap/src/test.rs @@ -30,7 +30,7 @@ fn test_header() { assert!(header.bit_id == id * BLOCK_BITS as u64); if let Err(e) = header.validate(BIT_ARRAY, id) { - panic!("Validation failed: {}", e); + panic!("Validation failed: {e}",); } header.magic ^= 1; @@ -138,7 +138,7 @@ fn test_basic_bitmap() { let mut bitmap = BitMap::create(file).unwrap(); if let Err(e) = bitmap.write() { - panic!("Write failed: {}", e); + panic!("Write failed: {e}",); } // Check our definition of the checksum of an empty tree. @@ -184,15 +184,15 @@ fn test_basic_bitmap() { // Try a flush now and then. if i % (BLOCK_BITS / 2) == 0 { if let Err(e) = bitmap.flush_old(0) { - panic!("flush_old failed: {}", e); + panic!("flush_old failed: {e}",); } } } let checksum1 = bitmap.compute_checksum(); let checksum2 = bitmap.compute_checksum(); - println!("Checksum 1: {:?}", checksum1); - println!("Checksum 2: {:?}", checksum2); + println!("Checksum 1: {checksum1:?}",); + println!("Checksum 2: {checksum2:?}",); assert!(checksum1 == checksum2); bitmap.clear_checksum_cache(); @@ -203,7 +203,7 @@ fn test_basic_bitmap() { let s1 = bitmap.serialize_partial(vec![0, BLOCK_BITS], 1); if let Err(x) = BitMap::deserialize(&s1) { - panic!("deserialize(&s1) failed: {}", x); + panic!("deserialize(&s1) failed: {x}",); } // Pick a random version number and serialize the entire @@ -212,7 +212,7 @@ fn test_basic_bitmap() { let s2 = bitmap.serialize(sparse_version); if let Err(x) = BitMap::deserialize(&s2) { - panic!("deserialize(&s2) failed: {}", x); + panic!("deserialize(&s2) failed: {x}",); } // Create SparseMaps from the serialized forms. @@ -237,7 +237,7 @@ fn test_basic_bitmap() { // Check that the sparse bitmap matches the source bitmap. if bitmap_result != sparse_result { - panic!("Sparse mismatch at {}", i); + panic!("Sparse mismatch at {i}",); } // Now check the partial bitmap. @@ -284,11 +284,11 @@ fn test_basic_bitmap() { let bits_initialized = bitmap.size(); if let Err(e) = bitmap.write() { - panic!("write failed: {}", e); + panic!("write failed: {e}",); } if let Err(e) = bitmap.flush_old(0) { - panic!("flush_old failed: {}", e); + panic!("flush_old failed: {e}",); } assert!(bitmap.validate(true)); diff --git a/src/libs/globutils/src/lib.rs b/src/libs/globutils/src/lib.rs index f2da30690..ffa3c81ab 100644 --- a/src/libs/globutils/src/lib.rs +++ b/src/libs/globutils/src/lib.rs @@ -48,7 +48,7 @@ pub fn fresh_tmp_dir() -> PathBuf { // Convert a u64 into a string with commas. fn commas_u64(input: u64) -> String { if input < 10000 { - return format!("{}", input); + return format!("{input}",); } let mut value = input; @@ -62,7 +62,7 @@ fn commas_u64(input: u64) -> String { if value == 1000 { result = "1,000".to_owned() + &result; } else { - result = format!("{}", value) + &result; + result = format!("{value}",) + &result; } result diff --git a/src/libs/globutils/src/logging.rs b/src/libs/globutils/src/logging.rs index 0b257fcdf..81e1cba02 100644 --- a/src/libs/globutils/src/logging.rs +++ b/src/libs/globutils/src/logging.rs @@ -16,17 +16,17 @@ pub fn init_logging(verbose: Option<&str>) { env_filter = env_filter.add_directive(LevelFilter::DEBUG.into()); } else { env_filter = - env_filter.add_directive(format!("{}=debug", module).parse().unwrap()); + env_filter.add_directive(format!("{module}=debug",).parse().unwrap()); } } if let Ok(rust_log) = env::var("RUST_LOG") { - println!("{}", rust_log); + println!("{rust_log}",); if !rust_log.is_empty() { for directive in rust_log.split(',').filter_map(|s| match s.parse() { Ok(directive) => Some(directive), Err(err) => { - eprintln!("Ignoring directive `{}`: {}", s, err); + eprintln!("Ignoring directive `{s}`: {err}",); None } }) { diff --git a/src/libs/merkle_tree/src/lib.rs b/src/libs/merkle_tree/src/lib.rs index 4db52c3e1..1d81d8f8b 100644 --- a/src/libs/merkle_tree/src/lib.rs +++ b/src/libs/merkle_tree/src/lib.rs @@ -438,8 +438,7 @@ impl Block { for i in 0..limit { if self.hashes[i] == HashValue::new() { return Err(eg!(format!( - "Hash entry {} for block {} at level {} is invalid.", - i, id, level + "Hash entry {i} for block {id} at level {level} is invalid.", ))); } } @@ -583,7 +582,7 @@ impl Drop for AppendOnlyMerkle { #[inline(always)] fn drop(&mut self) { if let Err(e) = self.write() { - panic!("AppendOnlyMerkle: drop failed, err = {}", e); + panic!("AppendOnlyMerkle: drop failed, err = {e}",); } } } @@ -672,7 +671,7 @@ impl AppendOnlyMerkle { let save = path.to_owned() + &ext; if path::Path::new(&save).exists() { - return Err(eg!(format!("Rebuild path {} already exists.", save))); + return Err(eg!(format!("Rebuild path {save} already exists.",))); } // Rename the level zero file out of the way and then create @@ -709,7 +708,7 @@ impl AppendOnlyMerkle { let file_size = input.seek(SeekFrom::End(0)).c(d!())?; let block_count = file_size / BLOCK_SIZE as u64; - input.seek(SeekFrom::Start(0)).c(d!())?; + input.rewind().c(d!())?; self.files[0] = input; let mut entries = 0; @@ -807,8 +806,7 @@ impl AppendOnlyMerkle { Ok(b) => b, Err(x) => { return Err(eg!(format!( - "Reconstruction of block {} at level {} failed: {}", - block_id, level, x + "Reconstruction of block {block_id} at level {level} failed: {x}", ))); } }; @@ -907,7 +905,7 @@ impl AppendOnlyMerkle { let path = self.path.clone(); let extension = if level > 0 { - format!(".{}", level) + format!(".{level}",) } else { "".to_string() }; @@ -966,7 +964,7 @@ impl AppendOnlyMerkle { return self.recover_file(level); } - if self.files[level].seek(SeekFrom::Start(0)).is_err() { + if self.files[level].rewind().is_err() { return self.recover_file(level); } @@ -1251,7 +1249,7 @@ impl AppendOnlyMerkle { let (block, prev) = items; if let Err(x) = block.set_hash(¤t_hash) { - return Err(eg!(format!("The tree is corrupted: set_hash: {}", x))); + return Err(eg!(format!("The tree is corrupted: set_hash: {x}",))); } // If the block is full, and all the previous blocks are @@ -1344,8 +1342,7 @@ impl AppendOnlyMerkle { pub fn generate_proof(&self, transaction_id: u64, version: u64) -> Result { if transaction_id >= self.entry_count { return Err(eg!(format!( - "That transaction id ({}) does not exist.", - transaction_id + "That transaction id ({transaction_id}) does not exist.", ))); } @@ -1696,8 +1693,7 @@ impl AppendOnlyMerkle { Ok(n) => { if n != start_offset { return Err(eg!(format!( - "A seek to {} returned {}.", - start_offset, n + "A seek to {start_offset} returned {n}.", ))); } } @@ -1721,8 +1717,7 @@ impl AppendOnlyMerkle { if i < total_blocks - 1 && !block.full() { return Err(eg!(format!( - "Block {} at level {} should be full.", - i, level + "Block {i} at level {level} should be full.", ))); } @@ -1772,8 +1767,7 @@ impl AppendOnlyMerkle { if disk_bytes != expected_size { return Err(eg!(format!( - "check_disk: The file size ({}) at level {} should be {}.", - disk_bytes, level, expected_size + "check_disk: The file size ({disk_bytes}) at level {level} should be {expected_size}.", ))); } @@ -1783,13 +1777,12 @@ impl AppendOnlyMerkle { if flushed && blocks_on_disk != list_length { return Err(eg!(format!( - "check_disk: The count {} at level {} should be {}.", - blocks_on_disk, level, list_length + "check_disk: The count {blocks_on_disk} at level {level} should be {list_length}.", ))); } - if let Err(x) = self.files[level].seek(SeekFrom::Start(0)) { - return Err(eg!(format!("check_disk: The read seek failed: {}", x))); + if let Err(x) = self.files[level].rewind() { + return Err(eg!(format!("check_disk: The read seek failed: {x}",))); } let mut entry_count = 0_u64; @@ -1817,7 +1810,7 @@ impl AppendOnlyMerkle { current.push(block); } Err(x) => { - return Err(eg!(format!("check_disk: A read failed: {}", x))); + return Err(eg!(format!("check_disk: A read failed: {x}",))); } } } @@ -1828,9 +1821,8 @@ impl AppendOnlyMerkle { // contents if the memory has been flushed. if flushed && entry_count != entries_at_this_level { return Err(eg!(format!( - "check_disk: The entry counts ({}, {}) \ - at level {} didn't match.", - entry_count, entries_at_this_level, level + "check_disk: The entry counts ({entry_count}, {entries_at_this_level}) \ + at level {level} didn't match.", ))); } @@ -1936,8 +1928,7 @@ impl AppendOnlyMerkle { if !last && !last_block_full { return Err(eg!(format!( - "check: Block {} at level {} should be full.", - block_id, level + "check: Block {block_id} at level {level} should be full.", ))); } @@ -1957,8 +1948,7 @@ impl AppendOnlyMerkle { if leaf_count != leaves_at_this_level { return Err(eg!(format!( - "check: The entry counts ({}, {}) at level {} did not match", - leaf_count, leaves_at_this_level, level + "check: The entry counts ({leaf_count}, {leaves_at_this_level}) at level {level} did not match", ))); } @@ -1974,9 +1964,8 @@ impl AppendOnlyMerkle { if last_level && leaves_at_this_level > 0 { return Err(eg!(format!( - "Level {} has {} blocks, with {} upper leaves, \ + "Level {level} has {last_blocks} blocks, with {leaves_at_this_level} upper leaves, \ but no levels remain.", - level, last_blocks, leaves_at_this_level ))); } } @@ -2088,7 +2077,7 @@ mod tests { #[test] fn test_info() { println!("The block size is {} bytes.", mem::size_of::()); - println!("A block contains {} leaves.", LEAVES_IN_BLOCK); + println!("A block contains {LEAVES_IN_BLOCK} leaves.",); } // Do some basic tests on the block header code to make sure that @@ -2098,7 +2087,7 @@ mod tests { let mut header = BlockHeader::new(3, 5); if let Err(e) = header.check(3, 5) { - panic!("new() returned an invalid header: {}", e); + panic!("new() returned an invalid header: {e}",); } header.header_mark ^= 1; @@ -2131,7 +2120,7 @@ mod tests { fn check_block(block: &Block, level: usize, id: u64, disk_format: bool) { if let Err(e) = block.check(level, id, disk_format) { - panic!("Unexpected block check error: {}", e); + panic!("Unexpected block check error: {e}",); } } @@ -2162,13 +2151,13 @@ mod tests { hash.hash[1] = (i & 0xff) as u8; if let Err(e) = block.set_hash(&hash) { - panic!("Unexpected set_hash error: {} at {}", e, i); + panic!("Unexpected set_hash error: {e} at {i}"); } block.set_checksum(); if let Err(e) = block.check(1, 2, false) { - panic!("Block check failure at iteration {}: {}", i, e); + panic!("Block check failure at iteration {i}: {e}"); } // If the block is not full, there will still be hash entries @@ -2211,7 +2200,7 @@ mod tests { check_block(&block, 1, 2, false); if block.valid_leaves() != i as u64 + 1 { - panic!("valid_leaves() should be {}", i); + panic!("valid_leaves() should be {i}",); } if !block.full() { @@ -2226,7 +2215,7 @@ mod tests { let error = block.set_hash(&hash); if let Ok(()) = error { - panic!("Missing error at iteration {}.", i); + panic!("Missing error at iteration {i}.",); } } @@ -2237,7 +2226,7 @@ mod tests { // Now check that mismatched block ids and levels are // caught. First, make sure that the block is valid. if let Err(e) = block.check(1, 2, false) { - panic!("The block was corrupted by set_hash: {}", e); + panic!("The block was corrupted by set_hash: {e}",); } if block.check(0, 2, false).is_ok() { @@ -2258,7 +2247,7 @@ mod tests { block.header.check_bits.bits[0] ^= 1; if let Err(e) = block.check(1, 2, false) { - panic!("Testing error: {}", e); + panic!("Testing error: {e}",); } // Now corrupt checksum[last] and do the checks. @@ -2271,7 +2260,7 @@ mod tests { block.header.check_bits.bits[CHECK_SIZE - 1] ^= 1; if let Err(e) = block.check(1, 2, false) { - panic!("Testing error: {}", e); + panic!("Testing error: {e}",); } // Okay, corrupt a hash in the subtree. @@ -2333,7 +2322,7 @@ mod tests { let mut tree = match result { Ok(tree) => tree, Err(x) => { - panic!("Unexpected error: {}", x); + panic!("Unexpected error: {x}",); } }; @@ -2341,7 +2330,7 @@ mod tests { check_tree(&tree); if let Err(x) = AppendOnlyMerkle::open(&path) { - panic!("read() got an error: {}", x); + panic!("read() got an error: {x}",); } if tree.path() != path { @@ -2360,7 +2349,7 @@ mod tests { tree = match AppendOnlyMerkle::open(&path) { Err(x) => { - panic!("Open failed: {}", x); + panic!("Open failed: {x}",); } Ok(x) => x, }; @@ -2386,7 +2375,7 @@ mod tests { // Check that the image can be read and is reasonable. match AppendOnlyMerkle::open(&path) { Err(x) => { - panic!("The open failed: {}", x); + panic!("The open failed: {x}",); } Ok(new_tree) => { if new_tree.total_size() != tree.total_size() { @@ -2398,12 +2387,12 @@ mod tests { let level_path = tree.file_path(1); if let Err(x) = fs::remove_file(&level_path) { - panic!("remove_file failed: {}", x); + panic!("remove_file failed: {x}",); } let mut tree = match AppendOnlyMerkle::open(&path) { Err(x) => { - panic!("Open failed to rebuild: {}", x); + panic!("Open failed to rebuild: {x}",); } Ok(tree) => tree, }; @@ -2415,7 +2404,7 @@ mod tests { // Now make sure that the new write path deals well with // disk reset operations. if let Err(e) = tree.reset_disk() { - panic!("Unexpected error: {}", e); + panic!("Unexpected error: {e}",); } for _i in 0..2 * LEAVES_IN_BLOCK { @@ -2455,25 +2444,25 @@ mod tests { fn check_tree(tree: &AppendOnlyMerkle) { if let Err(e) = tree.check() { - panic!("Got check error: {}", e); + panic!("Got check error: {e}",); } } fn check_disk_tree(tree: &mut AppendOnlyMerkle, flushed: bool) { if let Err(e) = tree.check_disk(flushed) { - panic!("Got disk check error: {}", e); + panic!("Got disk check error: {e}",); } } fn write_tree(tree: &mut AppendOnlyMerkle) { if let Err(e) = tree.write() { - panic!("tree.write failed: {}", e); + panic!("tree.write failed: {e}",); } } fn reset_tree(tree: &mut AppendOnlyMerkle) { if let Err(e) = tree.reset_disk() { - panic!("tree.reset_disk failed: {}", e); + panic!("tree.reset_disk failed: {e}",); } } @@ -2482,7 +2471,7 @@ mod tests { let result = tree.append_hash(&hash); if let Err(x) = result { - panic!("append_hash failed: {}", x); + panic!("append_hash failed: {x}",); } result.unwrap() @@ -2500,7 +2489,7 @@ mod tests { let mut tree = match result { Err(x) => { - panic!("Unexpected error: {}", x); + panic!("Unexpected error: {x}",); } Ok(tree) => tree, }; @@ -2544,7 +2533,7 @@ mod tests { check_disk_tree(&mut tree, false); if let Err(x) = AppendOnlyMerkle::open(&path) { - panic!("Open failed: {}", x); + panic!("Open failed: {x}",); } } @@ -2577,11 +2566,11 @@ mod tests { // Try a reconstruct match tree.reconstruct(1, 0) { Err(x) => { - panic!("reconstruct failed: {}", x); + panic!("reconstruct failed: {x}",); } Ok(block) => { if let Err(e) = block.check(1, 0, true) { - panic!("The reconstruct block is bad: {}", e); + panic!("The reconstruct block is bad: {e}",); } for i in 0..HASHES_IN_BLOCK { @@ -2630,7 +2619,7 @@ mod tests { check_disk_tree(&mut tree, true); if let Err(x) = AppendOnlyMerkle::open(&path) { - panic!("open failed: {}", x); + panic!("open failed: {x}",); } reset_tree(&mut tree); @@ -2662,7 +2651,7 @@ mod tests { match result { Err(x) => { - panic!("The open failed: {}", x); + panic!("The open failed: {x}",); } Ok(x) => { tree = x; @@ -2685,7 +2674,7 @@ mod tests { // Okay, do a minimal test of the rewrite function. if let Err(e) = tree.reset_disk() { - panic!("test_tree: failed at tree.reset_disk with error {}", e); + panic!("test_tree: failed at tree.reset_disk with error {e}",); } println!("Syncing and checking the reopened tree."); @@ -2697,7 +2686,7 @@ mod tests { let tree = match AppendOnlyMerkle::rebuild(&path) { Err(x) => { - panic!("Rebuild failed: {}", x); + panic!("Rebuild failed: {x}",); } Ok(tree) => tree, }; @@ -2710,7 +2699,7 @@ mod tests { for i in 0..count { if tree.leaf(i as usize) != create_test_hash(i, false) { - panic!("Leaf {} does not match.", i); + panic!("Leaf {i} does not match.",); } } @@ -2837,7 +2826,7 @@ mod tests { } } - println!("Got {} hashes.", count); + println!("Got {count} hashes.",); assert!(count == 9); let last = entry.hashes.len() - 1; println!("hashes[last = {}] = {}", last, entry.hashes[last].desc()); @@ -2870,7 +2859,7 @@ mod tests { let mut tree = match AppendOnlyMerkle::create(&path) { Ok(x) => x, Err(x) => { - panic!("Error on open: {}", x); + panic!("Error on open: {x}",); } }; @@ -2895,7 +2884,7 @@ mod tests { for i in 0..tree.total_size() { match tree.generate_proof(i, tree.total_size()) { Err(x) => { - panic!("Error on proof for transaction {}: {}", i, x); + panic!("Error on proof for transaction {i}: {x}"); } Ok(proof) => { check_proof(&tree, &proof, i); @@ -2918,7 +2907,7 @@ mod tests { let mut tree = match AppendOnlyMerkle::create(&path) { Ok(x) => x, Err(x) => { - panic!("Error on open: {}", x); + panic!("Error on open: {x}",); } }; @@ -2934,7 +2923,7 @@ mod tests { // of a test. match tree.generate_proof(id, tree.total_size()) { Err(x) => { - panic!("Error on proof for transaction {}: {}", i, x); + panic!("Error on proof for transaction {i}: {x}"); } Ok(proof) => { assert!(id == i); @@ -2961,7 +2950,7 @@ mod tests { // Generating a proof for a non-existent transaction // should fail. if let Ok(_x) = tree.generate_proof(transactions, tree.total_size()) { - panic!("Transaction {} does not exist.", transactions); + panic!("Transaction {transactions} does not exist.",); } // @@ -3009,7 +2998,7 @@ mod tests { let mut tree = match AppendOnlyMerkle::create(&path) { Ok(x) => x, Err(e) => { - panic!("Create failed: {}", e); + panic!("Create failed: {e}",); } }; @@ -3036,24 +3025,24 @@ mod tests { let mut tree: AppendOnlyMerkle = match serde_json::from_str(&encoded) { Ok(x) => x, Err(e) => { - panic!("from_str failed: {}", e); + panic!("from_str failed: {e}",); } }; if let Err(e) = tree.finish_deserialize() { - panic!("test_serde: tree.finish_deserialize failed with err {}", e); + panic!("test_serde: tree.finish_deserialize failed with err {e}",); } if let Err(e) = tree.check() { - panic!("test_serde: tree.check failed with err {}", e); + panic!("test_serde: tree.check failed with err {e}",); } if let Err(e) = tree.write() { - panic!("test_serde: tree.write failed with err {}", e); + panic!("test_serde: tree.write failed with err {e}",); } if let Err(e) = tree.check_disk(true) { - panic!("test_serde: tree.check_disk failed with err {}", e); + panic!("test_serde: tree.check_disk failed with err {e}",); } if tree.total_size() != size as u64 { @@ -3079,7 +3068,7 @@ mod tests { let mut tree = match AppendOnlyMerkle::create(&path) { Ok(x) => x, Err(e) => { - panic!("Create failed: {}", e); + panic!("Create failed: {e}",); } }; @@ -3093,11 +3082,11 @@ mod tests { match tree.reconstruct(1, 0) { Err(x) => { - panic!("Reconstruct failed: {}", x); + panic!("Reconstruct failed: {x}",); } Ok(block) => { if let Err(e) = block.check(1, 0, true) { - panic!("block.check failed with {}", e); + panic!("block.check failed with {e}",); } for i in 0..HASHES_IN_BLOCK { @@ -3160,7 +3149,7 @@ mod tests { let mut tree = match AppendOnlyMerkle::create(&path) { Ok(tree) => tree, Err(x) => { - panic!("create failed: {}", x); + panic!("create failed: {x}",); } }; @@ -3169,7 +3158,7 @@ mod tests { } if let Err(e) = tree.write() { - panic!("test_basic_rebuild: tree.write failed with {}", e); + panic!("test_basic_rebuild: tree.write failed with {e}",); } let fake = path.to_owned() + "." + &tree.files.len().to_string(); @@ -3177,9 +3166,9 @@ mod tests { let result = OpenOptions::new().create(true).write(true).open(&fake); if let Err(x) = result { - panic!("I cannot create {}: {}", fake, x); + panic!("I cannot create {fake}: {x}"); } else { - println!("Created {}.", fake); + println!("Created {fake}."); } let final_size = tree.total_size(); @@ -3188,7 +3177,7 @@ mod tests { let tree = match AppendOnlyMerkle::rebuild(&path) { Ok(tree) => tree, Err(x) => { - panic!("rebuild failed: {}", x); + panic!("rebuild failed: {x}",); } }; @@ -3202,7 +3191,7 @@ mod tests { for i in 0..4 * LEAVES_IN_BLOCK { if tree.leaf(i) != create_test_hash(i as u64, false) { - panic!("Leaf {} does not match.", i); + panic!("Leaf {i} does not match.",); } } @@ -3228,7 +3217,7 @@ mod tests { let result = fs::remove_file(&fake_ext); if let Err(x) = result { - panic!("File {} was not deleted: {}", fake_ext, x); + panic!("File {fake_ext} was not deleted: {x}"); } } } diff --git a/src/libs/sliding_set/src/lib.rs b/src/libs/sliding_set/src/lib.rs index 9fd715a6c..a6690ec02 100644 --- a/src/libs/sliding_set/src/lib.rs +++ b/src/libs/sliding_set/src/lib.rs @@ -65,15 +65,14 @@ impl SlidingSet { if index <= self.current && index + self.width >= (self.current + 1) { if self.map[index % self.width].contains(&key) { Err(eg!(format!( - "SlidingSet::insert: ({:?}, {}) already in set", - key, index + "SlidingSet::insert: ({key:?}, {index}) already in set", ))) } else { self.map[index % self.width].push(key); Ok(()) } } else { - Err(eg!(format!("({:?}, {}) is out of range", key, index))) + Err(eg!(format!("({key:?}, {index}) is out of range",))) } } } diff --git a/src/libs/sparse_merkle_tree/src/lib.rs b/src/libs/sparse_merkle_tree/src/lib.rs index df1b606a0..e06cace5c 100644 --- a/src/libs/sparse_merkle_tree/src/lib.rs +++ b/src/libs/sparse_merkle_tree/src/lib.rs @@ -480,7 +480,7 @@ mod tests { .unwrap() .as_nanos(); let mut path = temp_dir(); - path.push(format!("temp-findora-db–{}", time)); + path.push(format!("temp-findora-db–{time}",)); TempRocksDB::open(path).expect("failed to open rocksdb") } @@ -910,7 +910,7 @@ fn test_nullfier() { .unwrap() .as_nanos(); let mut path = temp_dir(); - path.push(format!("temp-findora-db–{}", time)); + path.push(format!("temp-findora-db–{time}",)); let rocksdb = TempRocksDB::open(path).expect("failed to open rocksdb"); let mut smt = SmtMap256::new(rocksdb); From ec880b33e1954625f38c3fc72df88d1bd1a3c387 Mon Sep 17 00:00:00 2001 From: shaorongqiang Date: Mon, 9 Jan 2023 10:02:33 +0800 Subject: [PATCH 05/10] add wasm new_keypair_old (#789) Co-authored-by: shaorongqiang --- src/components/wasm/src/wasm.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/components/wasm/src/wasm.rs b/src/components/wasm/src/wasm.rs index 9b7e96572..edb62015f 100644 --- a/src/components/wasm/src/wasm.rs +++ b/src/components/wasm/src/wasm.rs @@ -1596,6 +1596,11 @@ pub fn new_keypair() -> XfrKeyPair { gen_random_keypair() } +#[wasm_bindgen] +/// Creates a new transfer key pair. +pub fn new_keypair_old() -> XfrKeyPair { + XfrKeyPair::generate_ed25519(&mut ChaChaRng::from_entropy()) +} #[wasm_bindgen] /// Generates a new keypair deterministically from a seed string and an optional name. pub fn new_keypair_from_seed(seed_str: String, name: Option) -> XfrKeyPair { From c1995bda63fe4b887dca61fd630333816cf5fe4b Mon Sep 17 00:00:00 2001 From: liyue201 Date: Wed, 18 Jan 2023 10:58:31 +0800 Subject: [PATCH 06/10] Upgrade prism (#791) * Mint FRA for test address * upgrade prism * make fmt * make test * fix make test * fix withdraw_fra and parse_deposit_asset --- src/components/abciapp/Cargo.toml | 5 +- .../abciapp/src/abci/server/callback/mod.rs | 108 +++++-- .../abciapp/src/abci/staking/mod.rs | 137 +++------ src/components/config/src/abci/mod.rs | 7 +- src/components/contracts/baseapp/Cargo.toml | 3 +- src/components/contracts/baseapp/src/lib.rs | 36 +-- .../contracts/baseapp/src/modules.rs | 17 ++ .../evm/contracts/PrismXXBridge.abi.json | 266 ++++-------------- .../contracts/modules/evm/src/lib.rs | 62 +--- .../modules/evm/src/system_contracts.rs | 29 +- .../contracts/modules/evm/src/utils.rs | 197 ++++++------- 11 files changed, 293 insertions(+), 574 deletions(-) diff --git a/src/components/abciapp/Cargo.toml b/src/components/abciapp/Cargo.toml index aa1499ebe..f2a4e393c 100644 --- a/src/components/abciapp/Cargo.toml +++ b/src/components/abciapp/Cargo.toml @@ -58,7 +58,8 @@ tempfile = "3.1.0" baseapp = { path = "../contracts/baseapp" } fc-rpc = { path = "../contracts/rpc" } fp-storage = { path = "../contracts/primitives/storage" } -fp-utils = { path = "../contracts/primitives/utils" } +fp-types = {path = "../contracts/primitives/types"} +fp-utils = {path = "../contracts/primitives/utils" } enterprise-web3 = { path = "../contracts/primitives/enterprise-web3", optional = true } @@ -75,5 +76,5 @@ vergen = "=3.1.0" [features] default = ["diskcache"] diskcache = ["ledger/diskcache"] -debug_env = ["ledger/debug_env", "config/debug_env"] +debug_env = ["ledger/debug_env", "config/debug_env", "baseapp/debug_env"] web3_service = ["enterprise-web3", "baseapp/web3_service"] \ No newline at end of file diff --git a/src/components/abciapp/src/abci/server/callback/mod.rs b/src/components/abciapp/src/abci/server/callback/mod.rs index 8dacc1830..dd5244bdf 100644 --- a/src/components/abciapp/src/abci/server/callback/mod.rs +++ b/src/components/abciapp/src/abci/server/callback/mod.rs @@ -29,6 +29,7 @@ use { staking::KEEP_HIST, store::api_cache, }, + module_evm::utils::{deposit_asset_event_topic_str, parse_deposit_asset_event}, parking_lot::{Mutex, RwLock}, protobuf::RepeatedField, ruc::*, @@ -374,30 +375,85 @@ pub fn deliver_tx( } let mut resp = s.account_base_app.write().deliver_tx(req); - if td_height > CFG.checkpoint.fix_prism_mint_pay && 0 == resp.code { - let mut la = s.la.write(); - let mut laa = la.get_committed_state().write(); - if let Some(tx) = staking::system_prism_mint_pay( - &mut laa, - &mut s.account_base_app.write(), - ) { - drop(laa); - if la.cache_transaction(tx).is_ok() { - return resp; + if td_height > CFG.checkpoint.prismxx_inital_height && 0 == resp.code { + let deposit_asset_topic = deposit_asset_event_topic_str(); + + for evt in resp.events.iter() { + if evt.field_type == *"ethereum_ContractLog" { + let mut bridge_contract_found = false; + let mut deposit_asset_foud = false; + + for pair in evt.attributes.iter() { + let key = String::from_utf8(pair.key.clone()) + .unwrap_or_default(); + if key == *"address" { + let addr = String::from_utf8(pair.value.clone()) + .unwrap_or_default(); + if addr + == CFG + .checkpoint + .prism_bridge_address + .to_lowercase() + { + bridge_contract_found = true + } + } + if key == *"topics" { + let topic = String::from_utf8(pair.value.clone()) + .unwrap_or_default(); + if topic == deposit_asset_topic { + deposit_asset_foud = true + } + } + if key == *"data" + && bridge_contract_found + && deposit_asset_foud + { + let data = String::from_utf8(pair.value.clone()) + .unwrap_or_default(); + + let data_vec = serde_json::from_str(&data).unwrap(); + + let deposit_asset = + parse_deposit_asset_event(data_vec); + + match deposit_asset { + Ok(deposit) => { + let mut la = s.la.write(); + let mut laa = + la.get_committed_state().write(); + if let Some(tx) = + staking::system_prism_mint_pay( + &mut laa, deposit, + ) + { + drop(laa); + if la.cache_transaction(tx).is_ok() { + return resp; + } + resp.code = 1; + s.account_base_app + .read() + .deliver_state + .state + .write() + .discard_session(); + s.account_base_app + .read() + .deliver_state + .db + .write() + .discard_session(); + } + } + Err(e) => { + resp.code = 1; + resp.log = e.to_string(); + } + } + } + } } - resp.code = 1; - s.account_base_app - .read() - .deliver_state - .state - .write() - .discard_session(); - s.account_base_app - .read() - .deliver_state - .db - .write() - .discard_session(); } } resp @@ -434,11 +490,7 @@ pub fn end_block( // mint coinbase, cache system transactions to ledger { let mut laa = la.get_committed_state().write(); - if let Some(tx) = staking::system_mint_pay( - td_height, - &mut laa, - &mut s.account_base_app.write(), - ) { + if let Some(tx) = staking::system_mint_pay(td_height, &mut laa) { drop(laa); // this unwrap should be safe la.cache_transaction(tx).unwrap(); diff --git a/src/components/abciapp/src/abci/staking/mod.rs b/src/components/abciapp/src/abci/staking/mod.rs index 929f7c37d..532e0e2b3 100644 --- a/src/components/abciapp/src/abci/staking/mod.rs +++ b/src/components/abciapp/src/abci/staking/mod.rs @@ -12,8 +12,8 @@ mod test; use { crate::abci::server::callback::TENDERMINT_BLOCK_HEIGHT, abci::{Evidence, Header, LastCommitInfo, PubKey, ValidatorUpdate}, - baseapp::BaseApp as AccountBaseApp, config::abci::global_cfg::CFG, + fp_types::actions::xhub::NonConfidentialOutput, lazy_static::lazy_static, ledger::{ data_model::{ @@ -285,120 +285,57 @@ fn system_governance(staking: &mut Staking, bz: &ByzantineInfo) -> Result<()> { /// Pay for freed 'Delegations' and 'FraDistributions'. pub fn system_prism_mint_pay( la: &mut LedgerState, - account_base_app: &mut AccountBaseApp, + mint: NonConfidentialOutput, ) -> Option { let mut mints = Vec::new(); - if let Some(account_mint) = account_base_app.consume_mint() { - for mint in account_mint { - if mint.asset != ASSET_TYPE_FRA { - let atc = AssetTypeCode { val: mint.asset }; - let at = if let Some(mut at) = la.get_asset_type(&atc) { - at.properties.issuer = IssuerPublicKey { - key: *BLACK_HOLE_PUBKEY_STAKING, - }; - if mint.max_supply != 0 { - at.properties.asset_rules.max_units = Some(mint.max_supply); - } - at.properties.asset_rules.decimals = mint.decimal; - at - } else { - let mut at = AssetType::default(); - at.properties.issuer = IssuerPublicKey { - key: *BLACK_HOLE_PUBKEY_STAKING, - }; + if mint.asset != ASSET_TYPE_FRA { + let atc = AssetTypeCode { val: mint.asset }; + let at = if let Some(mut at) = la.get_asset_type(&atc) { + at.properties.issuer = IssuerPublicKey { + key: *BLACK_HOLE_PUBKEY_STAKING, + }; + if mint.max_supply != 0 { + at.properties.asset_rules.max_units = Some(mint.max_supply); + } + at.properties.asset_rules.decimals = mint.decimal; + at + } else { + let mut at = AssetType::default(); + at.properties.issuer = IssuerPublicKey { + key: *BLACK_HOLE_PUBKEY_STAKING, + }; - if mint.max_supply != 0 { - at.properties.asset_rules.max_units = Some(mint.max_supply); - } - at.properties.asset_rules.decimals = mint.decimal; + if mint.max_supply != 0 { + at.properties.asset_rules.max_units = Some(mint.max_supply); + } + at.properties.asset_rules.decimals = mint.decimal; - at.properties.code = AssetTypeCode { val: mint.asset }; + at.properties.code = AssetTypeCode { val: mint.asset }; - at - }; + at + }; - la.insert_asset_type(atc, at); - } + la.insert_asset_type(atc, at); + } - let mint_entry = MintEntry::new( - MintKind::Other, - mint.target, - None, - mint.amount, - mint.asset, - ); + let mint_entry = + MintEntry::new(MintKind::Other, mint.target, None, mint.amount, mint.asset); - mints.push(mint_entry); - } - } + mints.push(mint_entry); - if mints.is_empty() { - None - } else { - let mint_ops = - Operation::MintFra(MintFraOps::new(la.get_staking().cur_height(), mints)); - Some(Transaction::from_operation_coinbase_mint( - mint_ops, - la.get_state_commitment().1, - )) - } + let mint_ops = + Operation::MintFra(MintFraOps::new(la.get_staking().cur_height(), mints)); + Some(Transaction::from_operation_coinbase_mint( + mint_ops, + la.get_state_commitment().1, + )) } /// Pay for freed 'Delegations' and 'FraDistributions'. -pub fn system_mint_pay( - td_height: i64, - la: &mut LedgerState, - account_base_app: &mut AccountBaseApp, -) -> Option { +pub fn system_mint_pay(td_height: i64, la: &mut LedgerState) -> Option { let mut mints = Vec::new(); - if td_height <= CFG.checkpoint.fix_prism_mint_pay { - if let Some(account_mint) = account_base_app.consume_mint() { - for mint in account_mint { - if mint.asset != ASSET_TYPE_FRA { - let atc = AssetTypeCode { val: mint.asset }; - let at = if let Some(mut at) = la.get_asset_type(&atc) { - at.properties.issuer = IssuerPublicKey { - key: *BLACK_HOLE_PUBKEY_STAKING, - }; - - if mint.max_supply != 0 { - at.properties.asset_rules.max_units = Some(mint.max_supply); - } - - at - } else { - let mut at = AssetType::default(); - at.properties.issuer = IssuerPublicKey { - key: *BLACK_HOLE_PUBKEY_STAKING, - }; - - if mint.max_supply != 0 { - at.properties.asset_rules.max_units = Some(mint.max_supply); - } - - at.properties.code = AssetTypeCode { val: mint.asset }; - - at - }; - - la.insert_asset_type(atc, at); - } - - let mint_entry = MintEntry::new( - MintKind::Other, - mint.target, - None, - mint.amount, - mint.asset, - ); - - mints.push(mint_entry); - } - } - } - let staking = la.get_staking(); let mut limit = staking.coinbase_balance() as i128; diff --git a/src/components/config/src/abci/mod.rs b/src/components/config/src/abci/mod.rs index 9816f6d99..d50d80c13 100644 --- a/src/components/config/src/abci/mod.rs +++ b/src/components/config/src/abci/mod.rs @@ -61,7 +61,6 @@ pub struct CheckPointConfig { pub unbond_block_cnt: u64, pub prismxx_inital_height: i64, pub enable_triple_masking_height: i64, - pub fix_prism_mint_pay: i64, pub fix_exec_code: i64, // https://github.com/FindoraNetwork/platform/pull/307 @@ -118,13 +117,14 @@ impl CheckPointConfig { enable_triple_masking_height: 0, fix_unpaid_delegation_height: 0, fix_undelegation_missing_reward_height: 0, - fix_prism_mint_pay: 0, fix_exec_code: 0, evm_checktx_nonce: 0, utxo_checktx_height: 0, utxo_asset_prefix_height: 0, nonce_bug_fix_height: 0, - prism_bridge_address: String::new(), + prism_bridge_address: + "0xfcfe4ff1006a7721cee870b56ee2b5c250aec13b" + .to_owned(), proper_gas_set_height: 0, fix_delegators_am_height: 0, validators_limit_v2_height: 0, @@ -147,7 +147,6 @@ impl CheckPointConfig { prismxx_inital_height: 30000000, enable_triple_masking_height: 30000000, fix_unpaid_delegation_height: 2261885, - fix_prism_mint_pay: 30000000, fix_exec_code: 30000000, evm_checktx_nonce: 30000000, utxo_checktx_height: 30000000, diff --git a/src/components/contracts/baseapp/Cargo.toml b/src/components/contracts/baseapp/Cargo.toml index cbc641ceb..74bc31e81 100644 --- a/src/components/contracts/baseapp/Cargo.toml +++ b/src/components/contracts/baseapp/Cargo.toml @@ -56,4 +56,5 @@ evm-precompile = {path = "../modules/evm/precompile"} [features] abci_mock = [] -web3_service = ["enterprise-web3", "module-account/web3_service", "module-ethereum/web3_service", "module-evm/web3_service"] \ No newline at end of file +web3_service = ["enterprise-web3", "module-account/web3_service", "module-ethereum/web3_service", "module-evm/web3_service"] +debug_env = [] diff --git a/src/components/contracts/baseapp/src/lib.rs b/src/components/contracts/baseapp/src/lib.rs index f58a41134..3a899fe32 100644 --- a/src/components/contracts/baseapp/src/lib.rs +++ b/src/components/contracts/baseapp/src/lib.rs @@ -27,11 +27,11 @@ use fp_evm::BlockId; use fp_traits::{ account::{AccountAsset, FeeCalculator}, base::BaseProvider, - evm::{DecimalsMapping, EthereumAddressMapping, EthereumDecimalsMapping}, + evm::{EthereumAddressMapping, EthereumDecimalsMapping}, }; -use fp_types::{actions::xhub::NonConfidentialOutput, actions::Action, crypto::Address}; +use fp_types::{actions::Action, crypto::Address}; use lazy_static::lazy_static; -use ledger::data_model::{Transaction as FindoraTransaction, ASSET_TYPE_FRA}; +use ledger::data_model::Transaction as FindoraTransaction; use notify::*; use parking_lot::RwLock; use primitive_types::{H160, H256, U256}; @@ -350,36 +350,6 @@ impl BaseApp { self.modules .process_findora_tx(&self.deliver_state, tx, H256::from_slice(hash)) } - - pub fn consume_mint(&self) -> Option> { - let mut outputs = self.modules.evm_module.consume_mint(&self.deliver_state); - - for output in &outputs { - if output.asset == ASSET_TYPE_FRA { - let address = - Address::from(self.modules.evm_module.contracts.bridge_address); - if let Some(amount) = - EthereumDecimalsMapping::from_native_token(U256::from(output.amount)) - { - if let Err(e) = module_account::App::::burn( - &self.deliver_state, - &address, - amount, - ) { - tracing::error!("Error when burn account: {:?}", e); - } - } - } - } - - let outputs2 = module_xhub::App::::consume_mint(&self.deliver_state); - - if let Some(mut e) = outputs2 { - outputs.append(&mut e); - } - - Some(outputs) - } } impl BaseProvider for BaseApp { diff --git a/src/components/contracts/baseapp/src/modules.rs b/src/components/contracts/baseapp/src/modules.rs index 123db0093..42d2d6346 100644 --- a/src/components/contracts/baseapp/src/modules.rs +++ b/src/components/contracts/baseapp/src/modules.rs @@ -22,6 +22,9 @@ use module_ethereum::storage::{TransactionIndex, DELIVER_PENDING_TRANSACTIONS}; use ruc::*; use serde::Serialize; +#[cfg(feature = "debug_env")] +use std::str::FromStr; + #[derive(Default, Clone)] pub struct ModuleManager { // Ordered module list @@ -72,6 +75,20 @@ impl ModuleManager { self.evm_module.begin_block(ctx, req); self.xhub_module.begin_block(ctx, req); self.template_module.begin_block(ctx, req); + + #[cfg(feature = "debug_env")] + if ctx.header.height == 1 { + //private key: 4d05b965f821ea900ddd995dfa1b6caa834eaaa1ebe100a9760baf9331aae567 + let test_address = + H160::from_str("0x72488bAa718F52B76118C79168E55c209056A2E6").unwrap(); + + // mint 1000 FRA + pnk!(module_account::App::::mint( + ctx, + &Address::from(test_address), + U256::from(1_0000_0000_0000_0000_u64).saturating_mul(1000_00.into()) + )); + } } pub fn end_block( diff --git a/src/components/contracts/modules/evm/contracts/PrismXXBridge.abi.json b/src/components/contracts/modules/evm/contracts/PrismXXBridge.abi.json index 3defb48db..3909b8043 100644 --- a/src/components/contracts/modules/evm/contracts/PrismXXBridge.abi.json +++ b/src/components/contracts/modules/evm/contracts/PrismXXBridge.abi.json @@ -1,14 +1,40 @@ [ { + "anonymous": false, "inputs": [ { - "internalType": "address", - "name": "_proxy_contract", - "type": "address" + "indexed": false, + "internalType": "bytes32", + "name": "asset", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "receiver", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "decimal", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "max_supply", + "type": "uint256" } ], - "stateMutability": "nonpayable", - "type": "constructor" + "name": "DepositAsset", + "type": "event" }, { "anonymous": false, @@ -134,6 +160,19 @@ "name": "DepositFRC721", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -277,115 +316,6 @@ "name": "WithdrawFRC721", "type": "event" }, - { - "inputs": [], - "name": "__self", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "_consumeMint", - "outputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "asset", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "receiver", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "decimal", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "max_supply", - "type": "uint256" - } - ], - "internalType": "struct PrismXXBridge.MintOp[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "_asset", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "_from", - "type": "bytes" - }, - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "_withdrawAsset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address payable", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "_withdrawFRA", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -468,46 +398,6 @@ "stateMutability": "pure", "type": "function" }, - { - "inputs": [], - "name": "consumeMint", - "outputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "asset", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "receiver", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "decimal", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "max_supply", - "type": "uint256" - } - ], - "internalType": "struct PrismXXBridge.MintOp[]", - "name": "", - "type": "tuple[]" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -597,59 +487,14 @@ }, { "inputs": [], - "name": "ledger_contract", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "ops", - "outputs": [ - { - "internalType": "bytes32", - "name": "asset", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "receiver", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "decimal", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "max_supply", - "type": "uint256" - } - ], - "stateMutability": "view", + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], - "name": "owner", + "name": "ledger_contract", "outputs": [ { "internalType": "address", @@ -662,7 +507,7 @@ }, { "inputs": [], - "name": "proxy_contract", + "name": "owner", "outputs": [ { "internalType": "address", @@ -728,24 +573,19 @@ }, { "inputs": [ - { - "internalType": "bytes", - "name": "_from", - "type": "bytes" - }, { "internalType": "address payable", - "name": "_to", + "name": "to", "type": "address" }, { "internalType": "uint256", - "name": "_value", + "name": "value", "type": "uint256" }, { "internalType": "bytes", - "name": "_data", + "name": "data", "type": "bytes" } ], @@ -758,4 +598,4 @@ "stateMutability": "payable", "type": "receive" } -] +] \ No newline at end of file diff --git a/src/components/contracts/modules/evm/src/lib.rs b/src/components/contracts/modules/evm/src/lib.rs index 3839482c3..45e9d916f 100644 --- a/src/components/contracts/modules/evm/src/lib.rs +++ b/src/components/contracts/modules/evm/src/lib.rs @@ -12,7 +12,6 @@ pub mod system_contracts; pub mod utils; use abci::{RequestQuery, ResponseQuery}; -use config::abci::global_cfg::CFG; use ethabi::Token; use ethereum_types::{Bloom, BloomInput, H160, H256, U256}; use fp_core::{ @@ -37,7 +36,7 @@ use ethereum::{ }; use fp_types::{ - actions::{evm::Action, xhub::NonConfidentialOutput}, + actions::evm::Action, crypto::{Address, HA160}, }; use noah::xfr::sig::XfrPublicKey; @@ -46,7 +45,8 @@ use precompile::PrecompileSet; use ruc::*; use runtime::runner::ActionRunner; use std::marker::PhantomData; -use system_contracts::SystemContracts; +use std::str::FromStr; +use system_contracts::{SystemContracts, SYSTEM_ADDR}; pub use runtime::*; @@ -127,7 +127,7 @@ impl App { .encode_input(&[asset, from, to, value, lowlevel]) .c(d!())?; - let from = H160::zero(); + let from = H160::from_str(SYSTEM_ADDR).unwrap(); let gas_limit = 9999999; let value = U256::zero(); @@ -161,7 +161,7 @@ impl App { pub fn withdraw_fra( &self, ctx: &Context, - from: &XfrPublicKey, + _from: &XfrPublicKey, to: &H160, _value: U256, _lowlevel: Vec, @@ -170,23 +170,19 @@ impl App { ) -> Result<(TransactionV0, TransactionStatus, Receipt)> { let function = self.contracts.bridge.function("withdrawFRA").c(d!())?; - let from = Token::Bytes(from.noah_to_bytes()); - // let to = Token::Address(H160::from_slice(&bytes[4..24])); let to = Token::Address(*to); let value = Token::Uint(_value); let lowlevel = Token::Bytes(_lowlevel); - // println!("{:?}, {:?}, {:?}, {:?}", from, to, value, lowlevel); + //println!("{:?}, {:?}, {:?}, {:?}", from, to, value, lowlevel); - let input = function - .encode_input(&[from, to, value, lowlevel]) - .c(d!())?; + let input = function.encode_input(&[to, value, lowlevel]).c(d!())?; let gas_limit = 9999999; let value = U256::zero(); let gas_price = U256::one(); - let from = H160::zero(); + let from = H160::from_str(SYSTEM_ADDR).unwrap(); let (_, logs, used_gas) = ActionRunner::::execute_systemc_contract( ctx, @@ -214,22 +210,6 @@ impl App { )) } - pub fn consume_mint(&self, ctx: &Context) -> Vec { - let height = CFG.checkpoint.prismxx_inital_height; - - let mut pending_outputs = Vec::new(); - - if height < ctx.header.height { - if let Err(e) = - utils::fetch_mint::(ctx, &self.contracts, &mut pending_outputs) - { - tracing::error!("Collect mint ops error: {:?}", e); - } - } - - pending_outputs - } - fn logs_bloom(logs: &[ethereum::Log], bloom: &mut Bloom) { for log in logs { bloom.accrue(BloomInput::Raw(&log.address[..])); @@ -316,31 +296,7 @@ impl AppModule for App { } } - fn begin_block(&mut self, ctx: &mut Context, _req: &abci::RequestBeginBlock) { - let height = CFG.checkpoint.prismxx_inital_height; - - if ctx.header.height == height { - let bytecode_str = include_str!("../contracts/PrismXXProxy.bytecode"); - - if let Err(e) = - utils::deploy_contract::(ctx, &self.contracts, bytecode_str) - { - pd!(e); - return; - } - println!( - "Bridge contract address: {:?}", - self.contracts.bridge_address - ); - - if !ctx.state.write().cache_mut().good2_commit() { - ctx.state.write().discard_session(); - pd!(eg!("ctx state commit no good")); - } else { - ctx.state.write().commit_session(); - } - } - } + fn begin_block(&mut self, _ctx: &mut Context, _req: &abci::RequestBeginBlock) {} } impl Executable for App { diff --git a/src/components/contracts/modules/evm/src/system_contracts.rs b/src/components/contracts/modules/evm/src/system_contracts.rs index b910d3083..57c39cd99 100644 --- a/src/components/contracts/modules/evm/src/system_contracts.rs +++ b/src/components/contracts/modules/evm/src/system_contracts.rs @@ -2,49 +2,28 @@ use std::str::FromStr; use config::abci::global_cfg::CFG; use ethabi::Contract; -use ethereum_types::{H160, H256}; -use fp_utils::hashing::keccak_256; +use ethereum_types::H160; use ruc::*; use serde::{Deserialize, Serialize}; -use crate::utils; +pub static SYSTEM_ADDR: &str = "0x0000000000000000000000000000000000002000"; #[derive(Serialize, Deserialize, Debug, Clone)] pub struct SystemContracts { pub bridge: Contract, pub bridge_address: H160, - pub owner: H160, - pub salt: H256, } impl SystemContracts { pub fn new() -> Result { let abi_str = include_str!("../contracts/PrismXXBridge.abi.json"); let bridge = Contract::load(abi_str.as_bytes()).c(d!())?; - - let owner = - H160::from_str("0x72488bAa718F52B76118C79168E55c209056A2E6").c(d!())?; - - let salt = H256::zero(); - - let bridge_address = if CFG.checkpoint.prism_bridge_address.is_empty() { - // Driect use this bytecode, beacuse we will remove on mainnet - let bytecode_str = include_str!("../contracts/PrismXXProxy.bytecode"); - - let bytecode = hex::decode(bytecode_str[2..].trim()).c(d!())?; - - let code_hash = keccak_256(&bytecode); - - utils::compute_create2(owner, salt, H256::from_slice(&code_hash)) - } else { - H160::from_str(&CFG.checkpoint.prism_bridge_address).c(d!())? - }; + let bridge_address = + H160::from_str(&CFG.checkpoint.prism_bridge_address).unwrap_or_default(); Ok(Self { bridge, bridge_address, - owner, - salt, }) } } diff --git a/src/components/contracts/modules/evm/src/utils.rs b/src/components/contracts/modules/evm/src/utils.rs index 526fde4a0..386826560 100644 --- a/src/components/contracts/modules/evm/src/utils.rs +++ b/src/components/contracts/modules/evm/src/utils.rs @@ -1,137 +1,104 @@ -use ethabi::Token; -use ethereum_types::{H160, H256, U256}; -use fp_core::context::Context; +use ethabi::{Event, EventParam, ParamType, RawLog}; use fp_traits::evm::{DecimalsMapping, EthereumDecimalsMapping}; use fp_types::actions::xhub::NonConfidentialOutput; use ledger::data_model::ASSET_TYPE_FRA; +use noah::xfr::structs::ASSET_TYPE_LENGTH; use noah::xfr::{sig::XfrPublicKey, structs::AssetType}; use noah_algebra::serialization::NoahFromToBytes; use ruc::*; -use sha3::{Digest, Keccak256}; -use crate::{runner::ActionRunner, system_contracts::SystemContracts, Config}; - -pub fn deploy_contract( - ctx: &Context, - contracts: &SystemContracts, - bytecode_str: &str, -) -> Result<()> { - // Deploy Bridge here. - let bytecode = hex::decode(bytecode_str[2..].trim()).c(d!())?; - - ActionRunner::::inital_system_contract( - ctx, - bytecode, - 9999999999, - contracts.owner, - contracts.salt, - )?; - - Ok(()) -} - -pub fn fetch_mint( - ctx: &Context, - contracts: &SystemContracts, - outputs: &mut Vec, -) -> Result<()> { - let function = contracts.bridge.function("consumeMint").c(d!())?; - let input = function.encode_input(&[]).c(d!())?; - - let source = H160::zero(); - let target = contracts.bridge_address; - - let (ret, _, _) = ActionRunner::::execute_systemc_contract( - ctx, - input, - source, - 99999999, - target, - U256::zero(), - ) - .c(d!())?; - - let result = function.decode_output(&ret).c(d!())?; - - for v1 in result { - if let Token::Array(tokens) = v1 { - for token in tokens { - if let Token::Tuple(tuple) = token { - let output = parse_truple_result(tuple)?; - - tracing::info!("Got issue output: {:?}", output); - - outputs.push(output); - } - } - } +pub fn deposit_asset_event() -> Event { + Event { + name: "DepositAsset".to_owned(), + inputs: vec![ + EventParam { + name: "asset".to_owned(), + kind: ParamType::FixedBytes(32), + indexed: false, + }, + EventParam { + name: "receiver".to_owned(), + kind: ParamType::Bytes, + indexed: false, + }, + EventParam { + name: "amount".to_owned(), + kind: ParamType::Uint(256), + indexed: false, + }, + EventParam { + name: "decimal".to_owned(), + kind: ParamType::Uint(8), + indexed: false, + }, + EventParam { + name: "max_supply".to_owned(), + kind: ParamType::Uint(256), + indexed: false, + }, + ], + anonymous: false, } - - Ok(()) } -fn parse_truple_result(tuple: Vec) -> Result { - let asset = if let Token::FixedBytes(bytes) = - tuple.get(0).ok_or(eg!("Asset Must be FixedBytes"))? - { - let mut inner = [0u8; 32]; - - inner.copy_from_slice(bytes); - - AssetType(inner) - } else { - return Err(eg!("Asset Must be FixedBytes")); - }; +pub fn deposit_asset_event_topic_str() -> String { + let topic = deposit_asset_event().signature(); + let temp = hex::encode(topic.as_bytes()); + "[0x".to_owned() + &*temp + &*"]".to_owned() +} - let target = if let Token::Bytes(bytes) = - tuple.get(1).ok_or(eg!("Target must be FixedBytes"))? - { - XfrPublicKey::noah_from_bytes(bytes)? - } else { - return Err(eg!("Asset Must be FixedBytes")); +pub fn parse_deposit_asset_event(data: Vec) -> Result { + let event = deposit_asset_event(); + let log = RawLog { + topics: vec![event.signature()], + data, }; - - let amount = - if let Token::Uint(i) = tuple.get(2).ok_or(eg!("No asset in index 2"))? { - i - } else { - return Err(eg!("Amount must be uint")); - }; - - let amount = if asset == ASSET_TYPE_FRA { - EthereumDecimalsMapping::convert_to_native_token(*amount).as_u64() + let result = event.parse_log(log).c(d!())?; + + let asset = result.params[0] + .value + .clone() + .into_fixed_bytes() + .unwrap_or_default(); + let mut temp = [0u8; ASSET_TYPE_LENGTH]; + temp.copy_from_slice(asset.as_slice()); + let asset_type = AssetType(temp); + + let receiver = result.params[1] + .value + .clone() + .into_bytes() + .unwrap_or_default(); + let target = XfrPublicKey::noah_from_bytes(receiver.as_slice()).unwrap_or_default(); + + let amount = result.params[2] + .value + .clone() + .into_uint() + .unwrap_or_default(); + + let amount = if asset_type == ASSET_TYPE_FRA { + EthereumDecimalsMapping::convert_to_native_token(amount).as_u64() } else { amount.as_u64() }; - let decimal = - if let Token::Uint(decimal) = tuple.get(3).ok_or(eg!("No asset in index 3"))? { - decimal.as_u64() as u8 - } else { - return Err(eg!("Decimal must be uint")); - }; - - let max_supply = - if let Token::Uint(num) = tuple.get(4).ok_or(eg!("No asset in index 4"))? { - num.as_u64() - } else { - return Err(eg!("Max supply must be uint")); - }; + let decimal = result.params[3] + .value + .clone() + .into_uint() + .unwrap_or_default(); + let max_supply = result.params[4] + .value + .clone() + .into_uint() + .unwrap_or_default(); Ok(NonConfidentialOutput { - asset, + asset: asset_type, amount, target, - decimal, - max_supply, + decimal: decimal.as_u64() as u8, + max_supply: max_supply.as_u64(), }) } - -pub fn compute_create2(caller: H160, salt: H256, code_hash: H256) -> H160 { - let mut hasher = Keccak256::new(); - hasher.update([0xff]); - hasher.update(&caller[..]); - hasher.update(&salt[..]); - hasher.update(&code_hash[..]); - H256::from_slice(hasher.finalize().as_slice()).into() -} From 88fa8e7d115a73775b5000d7f10e70b93ae197e2 Mon Sep 17 00:00:00 2001 From: HarryLiIsMe <42673017+HarryLiIsMe@users.noreply.github.com> Date: Mon, 30 Jan 2023 14:15:42 +0800 Subject: [PATCH 07/10] prism bridge asdress update (#798) Co-authored-by: harry --- src/components/config/src/abci/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/config/src/abci/mod.rs b/src/components/config/src/abci/mod.rs index d50d80c13..b7768d9fc 100644 --- a/src/components/config/src/abci/mod.rs +++ b/src/components/config/src/abci/mod.rs @@ -123,7 +123,7 @@ impl CheckPointConfig { utxo_asset_prefix_height: 0, nonce_bug_fix_height: 0, prism_bridge_address: - "0xfcfe4ff1006a7721cee870b56ee2b5c250aec13b" + "0x5f9552fEd754F20B636C996DaDB32806554Bb995" .to_owned(), proper_gas_set_height: 0, fix_delegators_am_height: 0, From c2b27c5317b1ab91b67faaedb33113dbcd62d596 Mon Sep 17 00:00:00 2001 From: simonjiao Date: Wed, 1 Feb 2023 11:13:32 +0800 Subject: [PATCH 08/10] Fix reentrant hang issue (#707) * fix unhandled transaction * fix evm deliver_tx nonce * update startnodes.sh and checkpoint file --------- Co-authored-by: simonjiao --- src/components/config/src/abci/mod.rs | 6 + .../contracts/modules/ethereum/src/impls.rs | 165 ++++++++++-------- .../contracts/modules/ethereum/src/lib.rs | 40 +++++ .../primitives/core/src/transaction.rs | 30 +++- tools/devnet/startnodes.sh | 5 - 5 files changed, 164 insertions(+), 82 deletions(-) diff --git a/src/components/config/src/abci/mod.rs b/src/components/config/src/abci/mod.rs index b7768d9fc..0b0b4301f 100644 --- a/src/components/config/src/abci/mod.rs +++ b/src/components/config/src/abci/mod.rs @@ -88,6 +88,10 @@ pub struct CheckPointConfig { pub fix_delegators_am_height: u64, pub validators_limit_v2_height: u64, pub enable_eip1559_height: u64, + + // https://github.com/FindoraNetwork/platform/pull/707 + // FO-1370: V0.3.30 EVM bug: receipt missing when error code === 1 + pub fix_deliver_tx_revert_nonce_height: i64, } impl CheckPointConfig { @@ -129,6 +133,7 @@ impl CheckPointConfig { fix_delegators_am_height: 0, validators_limit_v2_height: 0, enable_eip1559_height: 0, + fix_deliver_tx_revert_nonce_height: 0, }; #[cfg(not(feature = "debug_env"))] let config = CheckPointConfig { @@ -158,6 +163,7 @@ impl CheckPointConfig { fix_delegators_am_height: 30000000, validators_limit_v2_height: 30000000, enable_eip1559_height: 40000000, + fix_deliver_tx_revert_nonce_height: 40000000, }; let content = toml::to_string(&config).unwrap(); file.write_all(content.as_bytes()).unwrap(); diff --git a/src/components/contracts/modules/ethereum/src/impls.rs b/src/components/contracts/modules/ethereum/src/impls.rs index 639098b04..be2f542d8 100644 --- a/src/components/contracts/modules/ethereum/src/impls.rs +++ b/src/components/contracts/modules/ethereum/src/impls.rs @@ -16,6 +16,7 @@ use fp_core::{ use fp_events::Event; use fp_evm::{BlockId, CallOrCreateInfo, Runner, TransactionStatus}; use fp_storage::{Borrow, BorrowMut}; +use fp_types::crypto::Address; use fp_types::{ actions::evm as EvmAction, crypto::{secp256k1_ecdsa_recover, HA256}, @@ -249,72 +250,95 @@ impl App { transaction.action, ); - if let Err(e) = execute_ret { - let mut to = Default::default(); - if let ethereum::TransactionAction::Call(target) = transaction.action { - to = target; - } - events.push(Event::emit_event( - Self::name(), - TransactionExecuted { - sender: source, - to, - contract_address: Default::default(), - transaction_hash, - reason: ExitReason::Fatal(ExitFatal::UnhandledInterrupt), - }, - )); - - return Ok(ActionResult { - code: 1, - data: vec![], - log: format!("{e}",), - gas_wanted: gas_limit.low_u64(), - gas_used: 0, - events, - }); - } + let (ar_code, info, to, contract_address, reason, data, status, used_gas) = + match execute_ret { + Err(e) => { + let to = if let ethereum::TransactionAction::Call(target) = + transaction.action + { + Some(target) + } else { + None + }; + + let logs = vec![ethereum::Log { + address: source, + topics: vec![], + data: format!("{e}").as_str().into(), + }]; + + let reason = ExitReason::Fatal(ExitFatal::UnhandledInterrupt); + let data = vec![]; + let status = TransactionStatus { + transaction_hash, + transaction_index, + from: source, + to, + contract_address: None, + logs: logs.clone(), + logs_bloom: { + let mut bloom: Bloom = Bloom::default(); + Self::logs_bloom(logs, &mut bloom); + bloom + }, + }; + let used_gas = U256::zero(); + + (Some(1), None, to, None, reason, data, status, used_gas) + } - let (to, contract_address, info) = execute_ret.unwrap(); - - let (reason, data, status, used_gas) = match info.clone() { - CallOrCreateInfo::Call(info) => ( - info.exit_reason, - info.value.clone(), - TransactionStatus { - transaction_hash, - transaction_index, - from: source, - to, - contract_address: None, - logs: info.logs.clone(), - logs_bloom: { - let mut bloom: Bloom = Bloom::default(); - Self::logs_bloom(info.logs, &mut bloom); - bloom - }, - }, - info.used_gas, - ), - CallOrCreateInfo::Create(info) => ( - info.exit_reason, - vec![], - TransactionStatus { - transaction_hash, - transaction_index, - from: source, - to, - contract_address: Some(info.value), - logs: info.logs.clone(), - logs_bloom: { - let mut bloom: Bloom = Bloom::default(); - Self::logs_bloom(info.logs, &mut bloom); - bloom - }, - }, - info.used_gas, - ), - }; + Ok((to, contract_address, info)) => { + let (reason, data, status, used_gas) = match info.clone() { + CallOrCreateInfo::Call(info) => ( + info.exit_reason, + info.value.clone(), + TransactionStatus { + transaction_hash, + transaction_index, + from: source, + to, + contract_address: None, + logs: info.logs.clone(), + logs_bloom: { + let mut bloom: Bloom = Bloom::default(); + Self::logs_bloom(info.logs, &mut bloom); + bloom + }, + }, + info.used_gas, + ), + CallOrCreateInfo::Create(info) => ( + info.exit_reason, + vec![], + TransactionStatus { + transaction_hash, + transaction_index, + from: source, + to, + contract_address: Some(info.value), + logs: info.logs.clone(), + logs_bloom: { + let mut bloom: Bloom = Bloom::default(); + Self::logs_bloom(info.logs, &mut bloom); + bloom + }, + }, + info.used_gas, + ), + }; + + ( + None, + Some(info), + to, + contract_address, + reason, + data, + status, + used_gas, + ) + } + }; for log in &status.logs { debug!(target: "ethereum", "transaction status log: block: {:?}, address: {:?}, topics: {:?}, data: {:?}", @@ -332,7 +356,7 @@ impl App { let (code, message) = match reason { ExitReason::Succeed(_) => (0, String::new()), - // code 1 indicates `Failed to execute evm function`, see above + // code 1 indicates `Failed to execute evm function`, see the `ar_code` ExitReason::Error(_) => (2, "EVM error".to_string()), ExitReason::Revert(_) => { let mut message = @@ -348,7 +372,9 @@ impl App { } (3, message) } - ExitReason::Fatal(_) => (4, "EVM Fatal error".to_string()), + ExitReason::Fatal(_) => { + (ar_code.unwrap_or(4), "EVM Fatal error".to_string()) + } }; if code != 0 { @@ -393,7 +419,10 @@ impl App { Ok(ActionResult { code, - data: serde_json::to_vec(&info).unwrap_or_default(), + source: Some(Address::from(source)), + data: info + .and_then(|i| serde_json::to_vec(&i).ok()) + .unwrap_or_default(), log: message, gas_wanted: gas_limit.low_u64(), gas_used: used_gas.low_u64(), diff --git a/src/components/contracts/modules/ethereum/src/lib.rs b/src/components/contracts/modules/ethereum/src/lib.rs index f32905238..33ae06e79 100644 --- a/src/components/contracts/modules/ethereum/src/lib.rs +++ b/src/components/contracts/modules/ethereum/src/lib.rs @@ -24,6 +24,7 @@ use fp_traits::{ use fp_types::{actions::ethereum::Action, crypto::Address}; use ruc::*; use std::marker::PhantomData; +use tracing::debug; pub const MODULE_NAME: &str = "ethereum"; @@ -234,6 +235,45 @@ impl ValidateUnsigned for App { Ok(()) } + + fn post_execute(ctx: &Context, result: &ActionResult) -> Result<()> { + if result.code != 0 + && ctx.header.height >= CFG.checkpoint.fix_deliver_tx_revert_nonce_height + { + let prev = result + .source + .as_ref() + .map(|who| C::AccountAsset::nonce(ctx, who)) + .unwrap_or_default(); + + ctx.state.write().discard_session(); + + // If EVM transaction fails, state change gets reverted/discarded except nonce. + let current = result + .source + .as_ref() + .map(|who| C::AccountAsset::nonce(ctx, who)) + .unwrap_or_default(); + + if prev.gt(¤t) { + if let Some(who) = result.source.as_ref() { + debug!( + target: + "baseapp", + "In post_execute: source {} {} {}", + who, + prev, + current + ); + // Keep it same with `pre_execute` + let _ = C::AccountAsset::inc_nonce(ctx, who); + } else { + unreachable!(); + } + } + } + Ok(()) + } } impl BlockHashMapping for App { diff --git a/src/components/contracts/primitives/core/src/transaction.rs b/src/components/contracts/primitives/core/src/transaction.rs index 1cc848dcf..efef55a6c 100644 --- a/src/components/contracts/primitives/core/src/transaction.rs +++ b/src/components/contracts/primitives/core/src/transaction.rs @@ -1,7 +1,7 @@ use crate::context::{Context, RunTxMode}; use abci::Event; use config::abci::global_cfg::CFG; -use fp_types::transaction::CheckedTransaction; +use fp_types::{crypto::Address, transaction::CheckedTransaction}; use impl_trait_for_tuples::impl_for_tuples; use ruc::*; use std::fmt::Debug; @@ -117,6 +117,12 @@ pub trait ValidateUnsigned { /// /// Changes made to storage should be discarded by caller. fn validate_unsigned(ctx: &Context, call: &Self::Call) -> Result<()>; + + /// Do any post-flight stuff for an transaction. + /// + fn post_execute(_ctx: &Context, _result: &ActionResult) -> Result<()> { + Ok(()) + } } impl Applyable for CheckedTransaction @@ -143,12 +149,12 @@ where U: ValidateUnsigned, U: Executable, { - let (maybe_who, pre) = if let Some((sender, extra)) = self.signed { + let (signed_tx, maybe_who, pre) = if let Some((sender, extra)) = self.signed { let pre = Extra::pre_execute(extra, ctx, &sender)?; - (Some(sender), pre) + (true, Some(sender), pre) } else { U::pre_execute(ctx, &self.function)?; - (None, Default::default()) + (false, None, Default::default()) }; ctx.state.write().commit_session(); @@ -167,12 +173,16 @@ where res.log = String::from("ctx state is not good to commit"); ctx.state.write().discard_session(); - } else if res.code == 0 { - Extra::post_execute(ctx, pre, &res)?; - - ctx.state.write().commit_session(); + } else if signed_tx { + if res.code == 0 { + Extra::post_execute(ctx, pre, &res)?; + ctx.state.write().commit_session(); + } else { + ctx.state.write().discard_session(); + } } else { - ctx.state.write().discard_session(); + U::post_execute(ctx, &res)?; + ctx.state.write().commit_session(); } ctx.db.write().commit_session(); @@ -198,6 +208,8 @@ pub struct ActionResult { /// 4 - EVM ExitReason::Fatal /// 0xff - context state maybe messed up pub code: u32, + /// Record the source address + pub source: Option
, /// Data is any data returned from message or handler execution. pub data: Vec, /// Log contains the log information from message or handler execution. diff --git a/tools/devnet/startnodes.sh b/tools/devnet/startnodes.sh index 12511316b..f887f5f23 100755 --- a/tools/devnet/startnodes.sh +++ b/tools/devnet/startnodes.sh @@ -2,11 +2,6 @@ # env source ./tools/devnet/env.sh || exit 1 -DEFAULT_BIN_CFG="release" -export BIN="target/$DEFAULT_BIN_CFG" - -$BIN/fn setup -S $ENDPOINT > /dev/null -$BIN/fn setup -O $WALLET/mnenomic.key > /dev/null # start one single node if specified Node="" From b602137e03ec730c1a9ba4525eb10793dcc74b4b Mon Sep 17 00:00:00 2001 From: simonjiao Date: Thu, 2 Feb 2023 00:43:49 +0800 Subject: [PATCH 09/10] Fo-1159 (#708) * honor block_number in call rpc * add clean_aux() fmerk update * enable snapshot * update storage version * rename trace/fresh options * update noah version * fix build error --------- Co-authored-by: simonjiao Co-authored-by: harry --- src/components/abciapp/Cargo.toml | 4 +- src/components/abciapp/src/abci/server/mod.rs | 8 ++- src/components/abciapp/src/bins/abcid.rs | 3 +- src/components/abciapp/src/bins/findorad.rs | 12 +++- src/components/config/src/abci/mod.rs | 39 +++++++++++++ src/components/config/src/findora/mod.rs | 39 +++++++++++++ src/components/contracts/baseapp/Cargo.toml | 4 +- src/components/contracts/baseapp/src/lib.rs | 44 +++++++++----- .../contracts/modules/account/Cargo.toml | 10 ++-- .../contracts/modules/ethereum/Cargo.toml | 4 +- .../contracts/modules/evm/Cargo.toml | 10 ++-- .../modules/evm/precompile/Cargo.toml | 4 +- .../modules/evm/src/runtime/runner.rs | 15 ++--- .../modules/evm/src/runtime/stack.rs | 17 ++++-- .../contracts/primitives/core/Cargo.toml | 4 +- .../contracts/primitives/core/src/context.rs | 16 +++++ .../contracts/primitives/mocks/Cargo.toml | 2 +- .../contracts/primitives/mocks/src/lib.rs | 5 +- .../contracts/primitives/storage/Cargo.toml | 4 +- .../contracts/primitives/types/Cargo.toml | 4 +- src/components/contracts/rpc/src/eth.rs | 58 ++++++++----------- src/components/finutils/Cargo.toml | 6 +- src/components/wallet_mobile/Cargo.toml | 4 +- src/components/wasm/Cargo.toml | 6 +- src/ledger/Cargo.toml | 12 ++-- src/libs/credentials/Cargo.toml | 2 +- src/libs/globutils/Cargo.toml | 6 +- src/libs/sparse_merkle_tree/Cargo.toml | 6 +- tools/devnet/env.sh | 6 +- 29 files changed, 237 insertions(+), 117 deletions(-) diff --git a/src/components/abciapp/Cargo.toml b/src/components/abciapp/Cargo.toml index f2a4e393c..0ec73a366 100644 --- a/src/components/abciapp/Cargo.toml +++ b/src/components/abciapp/Cargo.toml @@ -44,8 +44,8 @@ ruc = { version = "1.0.5", default-features = false, features = ["compact"] } module-evm = { path = "../contracts/modules/evm"} ethereum-types = { version = "0.13.1", default-features = false } -noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } -noah-algebra = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } +noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.2" } +noah-algebra = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.2" } abci = { git = "https://github.com/FindoraNetwork/tendermint-abci", tag = "0.7.5" } config = { path = "../config"} diff --git a/src/components/abciapp/src/abci/server/mod.rs b/src/components/abciapp/src/abci/server/mod.rs index 8983e406e..dc252eebd 100644 --- a/src/components/abciapp/src/abci/server/mod.rs +++ b/src/components/abciapp/src/abci/server/mod.rs @@ -56,13 +56,17 @@ impl ABCISubmissionServer { None => { pnk!(AccountBaseAPP::new( tempfile::tempdir().unwrap().path(), - CFG.disable_eth_empty_blocks + CFG.disable_eth_empty_blocks, + CFG.arc_history, + CFG.arc_fresh )) } Some(basedir) => { pnk!(AccountBaseAPP::new( Path::new(basedir), - CFG.disable_eth_empty_blocks + CFG.disable_eth_empty_blocks, + CFG.arc_history, + CFG.arc_fresh )) } }; diff --git a/src/components/abciapp/src/bins/abcid.rs b/src/components/abciapp/src/bins/abcid.rs index 949b61c50..0f78f14b4 100644 --- a/src/components/abciapp/src/bins/abcid.rs +++ b/src/components/abciapp/src/bins/abcid.rs @@ -13,8 +13,7 @@ use { fn main() { globutils::logging::init_logging(None); - - tracing::info!(concat!( + tracing::info!(target: "abciapp", concat!( "Build: ", env!("VERGEN_SHA"), " ", diff --git a/src/components/abciapp/src/bins/findorad.rs b/src/components/abciapp/src/bins/findorad.rs index cf450af88..6c66de5c3 100644 --- a/src/components/abciapp/src/bins/findorad.rs +++ b/src/components/abciapp/src/bins/findorad.rs @@ -49,6 +49,13 @@ fn node_command() -> Result<()> { .checkpoint_file .clone() .unwrap_or_else(|| String::from("./checkpoint.toml")); + let arc_history_arg = { + if let Some(interval) = CFG.arc_history.1 { + format!("{},{}", CFG.arc_history.0, interval) + } else { + format!("{}", CFG.arc_history.0) + } + }; abcid .arg("--submission-service-port") @@ -58,7 +65,9 @@ fn node_command() -> Result<()> { .arg("--checkpoint-file") .arg(&checkpoint_file) .arg("--ledger-dir") - .arg(&CFG.ledger_dir); + .arg(&CFG.ledger_dir) + .arg("--arc-history") + .arg(&arc_history_arg); for (condition, action) in [ (CFG.enable_query_service, "--enable-query-service"), @@ -67,6 +76,7 @@ fn node_command() -> Result<()> { (CFG.enable_snapshot, "--enable-snapshot"), (CFG.snapshot_list, "--snapshot-list"), (CFG.snapshot_rollback, "--snapshot-rollback"), + (CFG.arc_fresh, "--arc-fresh"), ] { if condition { abcid.arg(action); diff --git a/src/components/config/src/abci/mod.rs b/src/components/config/src/abci/mod.rs index 0b0b4301f..6c039a132 100644 --- a/src/components/config/src/abci/mod.rs +++ b/src/components/config/src/abci/mod.rs @@ -318,6 +318,8 @@ pub mod global_cfg { pub struct Config { pub abci_host: String, pub abci_port: u16, + pub arc_history: (u16, Option), + pub arc_fresh: bool, pub tendermint_host: String, pub tendermint_port: u16, pub submission_service_port: u16, @@ -351,6 +353,8 @@ pub mod global_cfg { .about("An ABCI node implementation of FindoraNetwork.") .arg_from_usage("--abcid-host=[ABCId IP]") .arg_from_usage("--abcid-port=[ABCId Port]") + .arg_from_usage("--arc-history=[EVM archive node tracing history, format \"PERIOD,INTERVAL\" in days]") + .arg_from_usage("--arc-fresh 'EVM archive node with fresh tracing history'") .arg_from_usage("--tendermint-host=[Tendermint IP]") .arg_from_usage("--tendermint-port=[Tendermint Port]") .arg_from_usage("--submission-service-port=[Submission Service Port]") @@ -394,6 +398,39 @@ pub mod global_cfg { .unwrap_or_else(|| "26658".to_owned()) .parse::() .c(d!("Invalid `abcid-port`."))?; + let arh = { + let trace = m + .value_of("arc-history") + .map(|v| v.to_owned()) + .or_else(|| env::var("ARC-HISTORY").ok()) + .unwrap_or_else(|| "90,10".to_string()) + .trim() + .to_owned(); + if trace.is_empty() { + return Err(eg!("empty trace")); + } + if trace.contains(',') { + let t = trace.split(',').collect::>(); + let trace = t + .first() + .expect("missing trace period") + .parse::() + .c(d!("invalid trace period"))?; + let interval = Some( + t.get(1) + .expect("missing trace interval") + .parse::() + .c(d!("invalid trace interval"))?, + ); + (trace, interval) + } else if !trace.is_empty() { + let trace = trace.parse::().c(d!("invalid trace period"))?; + (trace, None) + } else { + return Err(eg!("invalid trace")); + } + }; + let arf = m.is_present("arc-fresh"); let th = m .value_of("tendermint-host") .map(|v| v.to_owned()) @@ -465,6 +502,8 @@ pub mod global_cfg { let res = Config { abci_host: ah, abci_port: ap, + arc_history: arh, + arc_fresh: arf, tendermint_host: th, tendermint_port: tp, submission_service_port: ssp, diff --git a/src/components/config/src/findora/mod.rs b/src/components/config/src/findora/mod.rs index 36fa156c2..e4081b65b 100644 --- a/src/components/config/src/findora/mod.rs +++ b/src/components/config/src/findora/mod.rs @@ -151,6 +151,8 @@ pub mod config { pub struct Config { pub tendermint_host: String, pub tendermint_port: u16, + pub arc_history: (u16, Option), + pub arc_fresh: bool, pub submission_service_port: u16, pub ledger_service_port: u16, pub enable_query_service: bool, @@ -182,6 +184,8 @@ pub mod config { let node = SubCommand::with_name("node") .about("Start findora node.") .arg_from_usage("-c, --config=[FILE] 'Path to $TMHOM/config/config.toml'") + .arg_from_usage("--arc-history=[EVM archive node tracing history, format \"PERIOD,INTERVAL\" in days]") + .arg_from_usage("--arc-fresh 'EVM archive node with fresh tracing history'") .arg_from_usage("-H, --tendermint-host=[Tendermint Node IP]") .arg_from_usage("-P, --tendermint-port=[Tendermint Node Port]") .arg_from_usage("--submission-service-port=[Submission Service Port]") @@ -276,6 +280,39 @@ pub mod config { .unwrap_or_else(|| "26657".to_owned()) .parse::() .c(d!())?; + let arh = { + let trace = m + .value_of("arc-history") + .map(|v| v.to_owned()) + .or_else(|| env::var("ARC-HISTORY").ok()) + .unwrap_or_else(|| "90,10".to_string()) + .trim() + .to_owned(); + if trace.is_empty() { + return Err(eg!("empty trace")); + } + if trace.contains(',') { + let t = trace.split(',').collect::>(); + let trace = t + .first() + .expect("missing trace period") + .parse::() + .c(d!("invalid trace period"))?; + let interval = Some( + t.get(1) + .expect("missing trace interval") + .parse::() + .c(d!("invalid trace interval"))?, + ); + (trace, interval) + } else if !trace.is_empty() { + let trace = trace.parse::().c(d!("invalid trace period"))?; + (trace, None) + } else { + return Err(eg!("invalid trace")); + } + }; + let arf = m.is_present("arc-fresh"); let ssp = m .value_of("submission-service-port") .map(|v| v.to_owned()) @@ -336,6 +373,8 @@ pub mod config { let res = Config { tendermint_host: th, tendermint_port: tp, + arc_history: arh, + arc_fresh: arf, submission_service_port: ssp, ledger_service_port: lsp, enable_query_service: eqs, diff --git a/src/components/contracts/baseapp/Cargo.toml b/src/components/contracts/baseapp/Cargo.toml index 74bc31e81..493dcd3db 100644 --- a/src/components/contracts/baseapp/Cargo.toml +++ b/src/components/contracts/baseapp/Cargo.toml @@ -25,8 +25,8 @@ serde_json = "1.0.40" attohttpc = { version = "0.18", default-features = false, features = ["compress", "json", "tls-rustls"] } base64 = "0.13" once_cell = "1.10.0" -storage = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.0.0" } -fin_db = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.0.0" } +storage = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.1.4" } +fin_db = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.1.4" } sha3 = "0.8" config = { path = "../../config"} diff --git a/src/components/contracts/baseapp/src/lib.rs b/src/components/contracts/baseapp/src/lib.rs index 3a899fe32..2b808a323 100644 --- a/src/components/contracts/baseapp/src/lib.rs +++ b/src/components/contracts/baseapp/src/lib.rs @@ -37,22 +37,21 @@ use parking_lot::RwLock; use primitive_types::{H160, H256, U256}; use ruc::{eg, Result}; use std::{borrow::BorrowMut, path::Path, sync::Arc}; -use storage::state::ChainState; +use storage::state::{ChainState, ChainStateOpts}; +use tracing::info; lazy_static! { /// An identifier that distinguishes different EVM chains. static ref EVM_CAHIN_ID: u64 = std::env::var("EVM_CHAIN_ID").map( |id| id.as_str().parse::().unwrap()).unwrap_or(2152); - static ref CHAIN_STATE_MIN_VERSIONS: u64 = BLOCKS_IN_DAY * std::env::var("CHAIN_STATE_VERSIONS").map( - |ver|ver.as_str().parse::().expect("chainstate versions should be a valid integer") - ).unwrap_or(90); } const APP_NAME: &str = "findora"; const CHAIN_STATE_PATH: &str = "state.db"; const CHAIN_HISTORY_DATA_PATH: &str = "history.db"; const BLOCKS_IN_DAY: u64 = 4 * 60 * 24; +const SNAPSHOT_INTERVAL: u64 = 10 * 24; #[derive(Clone)] pub struct BaseApp { @@ -161,22 +160,33 @@ impl module_xhub::Config for BaseApp { } impl BaseApp { - pub fn new(basedir: &Path, empty_block: bool) -> Result { - tracing::info!( - "create new baseapp with basedir {:?}, empty_block {}, history {} blocks", - basedir, - empty_block, - *CHAIN_STATE_MIN_VERSIONS + pub fn new( + basedir: &Path, + empty_block: bool, + arc_history: (u16, Option), + is_fresh: bool, + ) -> Result { + info!( + target: "baseapp", + "create new baseapp with basedir {:?}, empty_block {}, trace history {:?} days, is_fresh {}", + basedir, empty_block, arc_history, is_fresh ); // Creates a fresh chain state db and history db let fdb_path = basedir.join(CHAIN_STATE_PATH); let fdb = FinDB::open(fdb_path.as_path())?; - let chain_state = Arc::new(RwLock::new(ChainState::new( - fdb, - "findora_db".to_owned(), - *CHAIN_STATE_MIN_VERSIONS, - ))); + + let opts = ChainStateOpts { + name: Some("findora_db".to_owned()), + ver_window: BLOCKS_IN_DAY * arc_history.0 as u64, + cleanup_aux: is_fresh, + interval: arc_history + .1 + .map_or(SNAPSHOT_INTERVAL * arc_history.0 as u64, |v| { + BLOCKS_IN_DAY * v as u64 + }), + }; + let chain_state = Arc::new(RwLock::new(ChainState::create_with_opts(fdb, opts))); let rdb_path = basedir.join(CHAIN_HISTORY_DATA_PATH); let rdb = RocksDB::open(rdb_path.as_path())?; @@ -298,6 +308,10 @@ impl BaseApp { } } + pub fn create_context_at(&self, height: u64) -> Option { + self.check_state.state_at(height) + } + /// retrieve the context for the txBytes and other memoized values. pub fn retrieve_context(&mut self, mode: RunTxMode) -> &mut Context { let ctx = if mode == RunTxMode::Deliver { diff --git a/src/components/contracts/modules/account/Cargo.toml b/src/components/contracts/modules/account/Cargo.toml index 73fe420c1..a22538a03 100644 --- a/src/components/contracts/modules/account/Cargo.toml +++ b/src/components/contracts/modules/account/Cargo.toml @@ -15,7 +15,7 @@ primitive-types = { version = "0.11.1", default-features = false, features = ["r ruc = "1.0" serde = { version = "1.0.124", features = ["derive"] } serde_json = "1.0.64" -storage = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.0.0" } +storage = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.1.4" } # primitives, don't depend on any modules fp-core = { path = "../../primitives/core" } @@ -28,9 +28,9 @@ config = {path = "../../../config"} [dev-dependencies] parking_lot = "0.12" rand_chacha = "0.3" -storage = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.0.0" } -fin_db = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.0.0" } -noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } +storage = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.1.4" } +fin_db = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.1.4" } +noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.2" } [features] -web3_service = ["enterprise-web3"] \ No newline at end of file +web3_service = ["enterprise-web3"] diff --git a/src/components/contracts/modules/ethereum/Cargo.toml b/src/components/contracts/modules/ethereum/Cargo.toml index 8f6ccaf0c..8b3243bdb 100644 --- a/src/components/contracts/modules/ethereum/Cargo.toml +++ b/src/components/contracts/modules/ethereum/Cargo.toml @@ -37,8 +37,8 @@ enterprise-web3 = { path = "../../primitives/enterprise-web3", optional = true baseapp = { path = "../../baseapp" } fp-mocks = { path = "../../primitives/mocks" } module-account = { path = "../account" } -storage = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.0.0" } -fin_db = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.0.0" } +storage = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.1.4" } +fin_db = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.1.4" } [features] default = [] diff --git a/src/components/contracts/modules/evm/Cargo.toml b/src/components/contracts/modules/evm/Cargo.toml index 6bac465ee..163e19cb4 100644 --- a/src/components/contracts/modules/evm/Cargo.toml +++ b/src/components/contracts/modules/evm/Cargo.toml @@ -24,8 +24,8 @@ serde_json = "1.0.64" sha3 = { version = "0.10", default-features = false } hex = "0.4.2" ethabi = "17.1.0" -noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } -noah-algebra = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } +noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.2" } +noah-algebra = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.2" } # primitives, don't depend on any modules fp-core = { path = "../../primitives/core" } @@ -35,8 +35,8 @@ fp-traits = { path = "../../primitives/traits" } fp-types = { path = "../../primitives/types" } fp-utils = { path = "../../primitives/utils" } config = { path = "../../../config"} -storage = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.0.0" } -fin_db = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.0.0" } +storage = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.1.4" } +fin_db = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.1.4" } ledger = { path = "../../../../ledger" } enterprise-web3 = { path = "../../primitives/enterprise-web3", optional = true } @@ -49,4 +49,4 @@ module-ethereum = { path = "../ethereum" } serde_json = "1.0.64" [features] -web3_service = ["enterprise-web3"] \ No newline at end of file +web3_service = ["enterprise-web3"] diff --git a/src/components/contracts/modules/evm/precompile/Cargo.toml b/src/components/contracts/modules/evm/precompile/Cargo.toml index 3e59e2ede..1b2cc1baf 100644 --- a/src/components/contracts/modules/evm/precompile/Cargo.toml +++ b/src/components/contracts/modules/evm/precompile/Cargo.toml @@ -17,7 +17,7 @@ evm-precompile-sha3fips = {path = "./sha3fips" } evm-precompile-modexp = { path = "./modexp" } evm-precompile-frc20 = { path = "./frc20" } evm-precompile-eth-pairings = { path = "./eth-pairings" } -storage = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v0.2.2" } +storage = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.1.4" } fp-core = { path = "../../../primitives/core" } parking_lot = "0.12" -fin_db = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v0.2.2" } +fin_db = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.1.4" } diff --git a/src/components/contracts/modules/evm/src/runtime/runner.rs b/src/components/contracts/modules/evm/src/runtime/runner.rs index 7525ac9b1..ffc945948 100644 --- a/src/components/contracts/modules/evm/src/runtime/runner.rs +++ b/src/components/contracts/modules/evm/src/runtime/runner.rs @@ -16,6 +16,7 @@ use fp_types::actions::evm::*; use ruc::*; use sha3::{Digest, Keccak256}; use std::marker::PhantomData; +use tracing::{debug, trace}; #[derive(Default)] pub struct ActionRunner { @@ -96,7 +97,7 @@ impl ActionRunner { let used_gas = U256::from(executor.used_gas()); let actual_fee = executor.fee(gas_price); - tracing::debug!( + debug!( target: "evm", "Execution {:?} [source: {:?}, value: {}, gas_price {}, gas_limit: {}, actual_fee: {}]", reason, @@ -115,7 +116,7 @@ impl ActionRunner { let state = executor.into_state(); for address in state.substate.deletes { - tracing::debug!( + debug!( target: "evm", "Deleting account at {:?}", address @@ -124,7 +125,7 @@ impl ActionRunner { } for log in &state.substate.logs { - tracing::trace!( + trace!( target: "evm", "Inserting log for {:?}, topics ({}) {:?}, data ({}): {:?}]", log.address, @@ -176,7 +177,7 @@ impl ActionRunner { let state = executor.into_state(); for address in state.substate.deletes { - tracing::debug!( + debug!( target: "evm", "Deleting account at {:?}", address @@ -185,7 +186,7 @@ impl ActionRunner { } for log in &state.substate.logs { - tracing::trace!( + trace!( target: "evm", "Inserting log for {:?}, topics ({}) {:?}, data ({}): {:?}]", log.address, @@ -232,7 +233,7 @@ impl ActionRunner { let state = executor.into_state(); for address in state.substate.deletes { - tracing::debug!( + debug!( target: "evm", "Deleting account at {:?}", address @@ -241,7 +242,7 @@ impl ActionRunner { } for log in &state.substate.logs { - tracing::trace!( + trace!( target: "evm", "Inserting log for {:?}, topics ({}) {:?}, data ({}): {:?}]", log.address, diff --git a/src/components/contracts/modules/evm/src/runtime/stack.rs b/src/components/contracts/modules/evm/src/runtime/stack.rs index ed8f9fd2d..b5d22ccad 100644 --- a/src/components/contracts/modules/evm/src/runtime/stack.rs +++ b/src/components/contracts/modules/evm/src/runtime/stack.rs @@ -15,7 +15,7 @@ use fp_traits::{ }; use fp_utils::timestamp_converter; use std::{collections::btree_set::BTreeSet, marker::PhantomData, mem}; -use tracing::info; +use tracing::{debug, error, info}; pub struct FindoraStackSubstate<'context, 'config> { pub ctx: &'context Context, @@ -284,7 +284,7 @@ impl<'context, 'vicinity, 'config, C: Config> StackState<'config> fn set_storage(&mut self, address: H160, index: H256, value: H256) { if value == H256::default() { - tracing::debug!( + debug!( target: "evm", "Removing storage for {:?} [index: {:?}]", address, @@ -296,7 +296,7 @@ impl<'context, 'vicinity, 'config, C: Config> StackState<'config> &index.into(), ); } else { - tracing::debug!( + debug!( target: "evm", "Updating storage for {:?} [index: {:?}, value: {:?}]", address, @@ -309,7 +309,7 @@ impl<'context, 'vicinity, 'config, C: Config> StackState<'config> &index.into(), &value, ) { - tracing::error!( + error!( target: "evm", "Failed updating storage for {:?} [index: {:?}, value: {:?}], error: {:?}", address, @@ -365,6 +365,11 @@ impl<'context, 'vicinity, 'config, C: Config> StackState<'config> } fn reset_storage(&mut self, address: H160) { + debug!( + target: "evm", + "Removing storage with prefix {:?}", + address, + ); AccountStorages::remove_prefix( self.ctx.state.write().borrow_mut(), &address.into(), @@ -381,7 +386,7 @@ impl<'context, 'vicinity, 'config, C: Config> StackState<'config> fn set_code(&mut self, address: H160, code: Vec) { let code_len = code.len(); - tracing::debug!( + debug!( target: "evm", "Inserting code ({} bytes) at {:?}", code_len, @@ -392,7 +397,7 @@ impl<'context, 'vicinity, 'config, C: Config> StackState<'config> let result = App::::create_account(self.ctx, address.into(), code); if let Err(e) = result { - tracing::error!( + error!( target: "evm", "Failed inserting code ({} bytes) at {:?}, error: {:?}", code_len, diff --git a/src/components/contracts/primitives/core/Cargo.toml b/src/components/contracts/primitives/core/Cargo.toml index 42d2a6f1b..292045260 100644 --- a/src/components/contracts/primitives/core/Cargo.toml +++ b/src/components/contracts/primitives/core/Cargo.toml @@ -16,8 +16,8 @@ parking_lot = "0.12" primitive-types = { version = "0.11.1", default-features = false, features = ["rlp", "byteorder", "serde"] } ruc = "1.0" serde = { version = "1.0.124", features = ["derive"] } -storage = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.0.0", optional = true } -fin_db = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.0.0", optional = true } +storage = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.1.4", optional = true } +fin_db = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.1.4", optional = true } serde_with = { version = "2.0.1"} # primitives diff --git a/src/components/contracts/primitives/core/src/context.rs b/src/components/contracts/primitives/core/src/context.rs index 3edf19d8a..d1d34c8df 100644 --- a/src/components/contracts/primitives/core/src/context.rs +++ b/src/components/contracts/primitives/core/src/context.rs @@ -53,6 +53,22 @@ impl Context { } } + pub fn state_at(&self, height: u64) -> Option { + let state = self.state.read().state_at(height); + let db = State::new(self.db.read().chain_state(), false); + match state { + Ok(state) => Some(Context { + state: Arc::new(RwLock::new(state)), + db: Arc::new(RwLock::new(db)), + run_mode: RunTxMode::None, + header: Default::default(), + header_hash: Default::default(), + eth_cache: Default::default(), + }), + _ => None, + } + } + pub fn copy_with_state(&self) -> Self { Context { state: Arc::new(RwLock::new(self.state.read().copy())), diff --git a/src/components/contracts/primitives/mocks/Cargo.toml b/src/components/contracts/primitives/mocks/Cargo.toml index 6feb0138e..ac613434c 100644 --- a/src/components/contracts/primitives/mocks/Cargo.toml +++ b/src/components/contracts/primitives/mocks/Cargo.toml @@ -18,7 +18,7 @@ rand_chacha = "0.3" rlp = "0.5" serde_json = "1.0" sha3 = "0.10" -noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } +noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.2" } # primitives fp-traits = { path = "../traits" } diff --git a/src/components/contracts/primitives/mocks/src/lib.rs b/src/components/contracts/primitives/mocks/src/lib.rs index e34b7fdd1..302bf14f2 100644 --- a/src/components/contracts/primitives/mocks/src/lib.rs +++ b/src/components/contracts/primitives/mocks/src/lib.rs @@ -23,8 +23,9 @@ use std::sync::Mutex; use std::time::SystemTime; lazy_static! { - pub static ref BASE_APP: Mutex = - Mutex::new(BaseApp::new(create_temp_db_path().as_path(), false).unwrap()); + pub static ref BASE_APP: Mutex = Mutex::new( + BaseApp::new(create_temp_db_path().as_path(), false, (0, None), false).unwrap() + ); pub static ref ALICE_ECDSA: KeyPair = generate_address(1); pub static ref BOB_ECDSA: KeyPair = generate_address(2); pub static ref ALICE_XFR: XfrKeyPair = diff --git a/src/components/contracts/primitives/storage/Cargo.toml b/src/components/contracts/primitives/storage/Cargo.toml index 7d74e505a..bdb5e4c61 100644 --- a/src/components/contracts/primitives/storage/Cargo.toml +++ b/src/components/contracts/primitives/storage/Cargo.toml @@ -15,10 +15,10 @@ ruc = "1.0" serde = { version = "1.0.124", features = ["derive"] } serde_json = "1.0" sha2 = "0.10" -storage = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.0.0" } +storage = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.1.4" } # primitives fp-core = { path = "../core" } [dev-dependencies] -temp_db = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.0.0" } +temp_db = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.1.4" } diff --git a/src/components/contracts/primitives/types/Cargo.toml b/src/components/contracts/primitives/types/Cargo.toml index 21242aea8..d840c46cf 100644 --- a/src/components/contracts/primitives/types/Cargo.toml +++ b/src/components/contracts/primitives/types/Cargo.toml @@ -21,8 +21,8 @@ serde = { version = "1.0.124", features = ["derive"] } serde_json = "1.0" serde-big-array = "0.4" sha3 = "0.10" -noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } -noah-algebra = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } +noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.2" } +noah-algebra = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.2" } # primitives fp-utils = { path = "../utils" } diff --git a/src/components/contracts/rpc/src/eth.rs b/src/components/contracts/rpc/src/eth.rs index 22beb8cbd..042f59104 100644 --- a/src/components/contracts/rpc/src/eth.rs +++ b/src/components/contracts/rpc/src/eth.rs @@ -360,9 +360,9 @@ impl EthApi for EthApiImpl { fn call( &self, request: CallRequest, - _: Option, + block_number: Option, ) -> BoxFuture> { - debug!(target: "eth_rpc", "call, request:{:?}", request); + debug!(target: "eth_rpc", "call, height {:?}, request:{:?}", block_number, request); let mut request = request; let curr_height = match self.block_number() { @@ -412,18 +412,14 @@ impl EthApi for EthApiImpl { nonce, } = request; - let block = account_base_app.read().current_block(None); + let id = native_block_id(block_number); + let block = account_base_app + .read() + .current_block(id) + .ok_or_else(|| internal_err("failed to get block"))?; + // use given gas limit or query current block's limit - let gas_limit = match gas { - Some(amount) => amount, - None => { - if let Some(block) = block.clone() { - block.header.gas_limit - } else { - ::BlockGasLimit::get() - } - } - }; + let gas_limit = gas.unwrap_or(block.header.gas_limit); let data = data.map(|d| d.0).unwrap_or_default(); let mut config = ::config().clone(); @@ -431,18 +427,13 @@ impl EthApi for EthApiImpl { let mut ctx = account_base_app .read() - .create_query_context(None, false) - .map_err(|err| { - internal_err(format!("create query context error: {err:?}",)) - })?; - if let Some(block) = block { - ctx.header - .mut_time() - .set_seconds(block.header.timestamp as i64); - ctx.header.height = block.header.number.as_u64() as i64; - ctx.header.proposer_address = - Vec::from(block.header.beneficiary.as_bytes()) - } + .create_context_at(block.header.number.as_u64()) + .ok_or_else(|| internal_err("create query context error"))?; + ctx.header + .mut_time() + .set_seconds(block.header.timestamp as i64); + ctx.header.height = block.header.number.as_u64() as i64; + ctx.header.proposer_address = Vec::from(block.header.beneficiary.as_bytes()); match to { Some(to) => { @@ -993,14 +984,15 @@ impl EthApi for EthApiImpl { } let allowance = available / gas_price; if highest < allowance { - tracing::warn!( - "Gas estimation capped by limited funds original {} balance {} sent {} feecap {} fundable {}", - highest, - balance, - request.value.unwrap_or_default(), - gas_price, - allowance - ); + warn!( + target: "eth_rpc", + "Gas estimation capped by limited funds original {} balance {} sent {} feecap {} fundable {}", + highest, + balance, + request.value.unwrap_or_default(), + gas_price, + allowance + ); highest = allowance; } } diff --git a/src/components/finutils/Cargo.toml b/src/components/finutils/Cargo.toml index 1782f2f98..01e29b35b 100644 --- a/src/components/finutils/Cargo.toml +++ b/src/components/finutils/Cargo.toml @@ -25,9 +25,9 @@ tokio = "1.10.1" wasm-bindgen = { version = "=0.2.73", features = ["serde-serialize"] } getrandom = "0.2" -noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } -noah-crypto = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } -noah-algebra = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } +noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.2" } +noah-crypto = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.2" } +noah-algebra = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.2" } ruc = "1.0" rucv3 = { package = "ruc", version = "3.0" } diff --git a/src/components/wallet_mobile/Cargo.toml b/src/components/wallet_mobile/Cargo.toml index 53086d49a..ae87fe366 100644 --- a/src/components/wallet_mobile/Cargo.toml +++ b/src/components/wallet_mobile/Cargo.toml @@ -32,8 +32,8 @@ serde = { version = "1.0.124", features = ["derive"] } serde_derive = "^1.0.59" serde_json = "1.0" -noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } -noah-algebra = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } +noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.2" } +noah-algebra = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.2" } finutils = { path = "../finutils", default-features = false, features = []} fp-types = { path = "../contracts/primitives/types" } diff --git a/src/components/wasm/Cargo.toml b/src/components/wasm/Cargo.toml index fbd9de16d..67b5f5550 100644 --- a/src/components/wasm/Cargo.toml +++ b/src/components/wasm/Cargo.toml @@ -36,9 +36,9 @@ ruc = "1.0" # OR the compiling will fail. getrandom = { version = "0.2", features = ["js"] } -noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } -noah-algebra = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } -noah-crypto = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } +noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.2" } +noah-algebra = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.2" } +noah-crypto = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.2" } finutils = { path = "../finutils", default-features = false } globutils = { path = "../../libs/globutils" } diff --git a/src/ledger/Cargo.toml b/src/ledger/Cargo.toml index b01a0231b..c11f12ea9 100644 --- a/src/ledger/Cargo.toml +++ b/src/ledger/Cargo.toml @@ -34,9 +34,9 @@ fp-utils = { path = "../components/contracts/primitives/utils" } itertools = "0.10" ruc = "1.0" -noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } -noah-crypto = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } -noah-algebra = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } +noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.2" } +noah-crypto = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.2" } +noah-algebra = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.2" } bulletproofs = { git = "https://github.com/FindoraNetwork/bulletproofs", tag = "v1.0.1-f" } fbnc = { version = "0.2.9", default-features = false} @@ -68,10 +68,10 @@ features = ["f16", "serde"] parking_lot = "0.12" # sodiumoxide = "0.2.1" fs2 = "0.4" -storage = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v0.2.2", optional = true } -fin_db = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v0.2.2", optional = true } +storage = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.1.4", optional = true } +fin_db = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.1.4", optional = true } sparse_merkle_tree = { path = "../libs/sparse_merkle_tree" } -noah-accumulators = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } +noah-accumulators = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.2" } [target.'cfg(target_arch = "wasm32")'.dependencies] parking_lot = { version = "0.11", features = ["wasm-bindgen"] } diff --git a/src/libs/credentials/Cargo.toml b/src/libs/credentials/Cargo.toml index 8b1819d3a..e470b6906 100644 --- a/src/libs/credentials/Cargo.toml +++ b/src/libs/credentials/Cargo.toml @@ -12,5 +12,5 @@ linear-map = {version = "1.2.0", features = ["serde_impl"] } serde = "1.0.124" serde_derive = "1.0" wasm-bindgen = { version = "=0.2.73", features = ["serde-serialize"] } -noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } +noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.2" } diff --git a/src/libs/globutils/Cargo.toml b/src/libs/globutils/Cargo.toml index 01bc71da1..fcc4613db 100644 --- a/src/libs/globutils/Cargo.toml +++ b/src/libs/globutils/Cargo.toml @@ -12,9 +12,9 @@ serde_json = "1.0" time = "0.3" rand = "0.8" cryptohash = { path = "../cryptohash" } -noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } -noah-crypto = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } -noah-algebra = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } +noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.2" } +noah-crypto = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.2" } +noah-algebra = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.2" } hex = "0.4.2" bip32 = "0.3.0" diff --git a/src/libs/sparse_merkle_tree/Cargo.toml b/src/libs/sparse_merkle_tree/Cargo.toml index aa3178d52..c90f569fd 100644 --- a/src/libs/sparse_merkle_tree/Cargo.toml +++ b/src/libs/sparse_merkle_tree/Cargo.toml @@ -23,9 +23,9 @@ serde = "1.0.124" serde_derive = "1.0" serde_json = "1.0" sha2 = "0.10" -storage = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v0.2.2" } -noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.0" } +storage = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.1.4" } +noah = { git = "https://github.com/FindoraNetwork/noah", tag = "v0.3.2" } [dev-dependencies] -temp_db = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v0.2.2" } +temp_db = { git = "https://github.com/FindoraNetwork/storage.git", tag = "v1.1.4" } quickcheck = "0.9.0" diff --git a/tools/devnet/env.sh b/tools/devnet/env.sh index a7be04db9..ff39e0979 100755 --- a/tools/devnet/env.sh +++ b/tools/devnet/env.sh @@ -35,11 +35,11 @@ PRIV_KEY="o9gXFI5ft1VOkzYhvFpgUTWVoskM1CEih0zJcm3-EAQ=" # create directories and file mkdir -p $WALLET mkdir -p $DEVNET -echo "$MNEMONIC" > $WALLET/mnenomic.key +echo "$MNEMONIC" >$WALLET/mnenomic.key # setup endpoint -$BIN/fn setup -S $ENDPOINT > /dev/null -$BIN/fn setup -O $WALLET/mnenomic.key > /dev/null +$BIN/fn setup -S $ENDPOINT >/dev/null +$BIN/fn setup -O $WALLET/mnenomic.key >/dev/null # show envs if [ "$1" == "s" ]; then From 5d0d3932171bb3ebcabfffb9b1875f5540226a1b Mon Sep 17 00:00:00 2001 From: harry Date: Tue, 7 Feb 2023 12:31:32 +0800 Subject: [PATCH 10/10] Fixed some codes from SimonJiao's comments --- src/components/config/src/abci/mod.rs | 1 + .../primitives/types/src/actions/ethereum.rs | 6 --- .../primitives/types/src/actions/mod.rs | 8 --- .../primitives/types/src/assemble.rs | 5 +- .../contracts/primitives/wasm/Cargo.toml | 1 + .../contracts/primitives/wasm/src/wasm.rs | 49 +++++++++++++------ 6 files changed, 36 insertions(+), 34 deletions(-) diff --git a/src/components/config/src/abci/mod.rs b/src/components/config/src/abci/mod.rs index 6c039a132..db3003392 100644 --- a/src/components/config/src/abci/mod.rs +++ b/src/components/config/src/abci/mod.rs @@ -87,6 +87,7 @@ pub struct CheckPointConfig { // Fix the amount in the delegators that staking did not modify when it punished the validator. pub fix_delegators_am_height: u64, pub validators_limit_v2_height: u64, + // eip1559 support switch. pub enable_eip1559_height: u64, // https://github.com/FindoraNetwork/platform/pull/707 diff --git a/src/components/contracts/primitives/types/src/actions/ethereum.rs b/src/components/contracts/primitives/types/src/actions/ethereum.rs index ce6271f04..5d26f65b8 100644 --- a/src/components/contracts/primitives/types/src/actions/ethereum.rs +++ b/src/components/contracts/primitives/types/src/actions/ethereum.rs @@ -1,13 +1,7 @@ use ethereum::TransactionV0 as LegcayTransaction; -use ethereum::TransactionV2 as Transaction; use serde::{Deserialize, Serialize}; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum Action { Transact(LegcayTransaction), } - -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -pub enum Action2 { - Transact(Transaction), -} diff --git a/src/components/contracts/primitives/types/src/actions/mod.rs b/src/components/contracts/primitives/types/src/actions/mod.rs index 4e07c8407..b049ae7d2 100644 --- a/src/components/contracts/primitives/types/src/actions/mod.rs +++ b/src/components/contracts/primitives/types/src/actions/mod.rs @@ -12,11 +12,3 @@ pub enum Action { XHub(xhub::Action), Template(template::Action), } - -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -pub enum Action2 { - Ethereum(ethereum::Action2), - Evm(evm::Action), - XHub(xhub::Action), - Template(template::Action), -} diff --git a/src/components/contracts/primitives/types/src/assemble.rs b/src/components/contracts/primitives/types/src/assemble.rs index 879b3dfff..41cdb5a16 100644 --- a/src/components/contracts/primitives/types/src/assemble.rs +++ b/src/components/contracts/primitives/types/src/assemble.rs @@ -1,5 +1,5 @@ use crate::actions::ethereum::Action as EtherAction; -use crate::actions::{Action, Action2}; +use crate::actions::Action; use crate::crypto::{Address, Signature}; use crate::transaction; use ethereum::TransactionV0 as Transaction; @@ -32,9 +32,6 @@ impl CheckFee { pub type UncheckedTransaction = transaction::UncheckedTransaction; -pub type UncheckedTransaction2 = - transaction::UncheckedTransaction; - /// Transaction type that has already been checked. pub type CheckedTransaction = transaction::CheckedTransaction; diff --git a/src/components/contracts/primitives/wasm/Cargo.toml b/src/components/contracts/primitives/wasm/Cargo.toml index cf8cc46db..196003b5b 100644 --- a/src/components/contracts/primitives/wasm/Cargo.toml +++ b/src/components/contracts/primitives/wasm/Cargo.toml @@ -21,6 +21,7 @@ fp-utils = { path = "../../primitives/utils" } rlp = "0.5" ruc = "1.0" sha3 = "0.10" +serde = { version = "1.0.124", features = ["derive"] } serde_json = "1.0" wasm-bindgen = { version = "=0.2.73", features = ["serde-serialize"] } diff --git a/src/components/contracts/primitives/wasm/src/wasm.rs b/src/components/contracts/primitives/wasm/src/wasm.rs index da4632e7e..13678d91c 100644 --- a/src/components/contracts/primitives/wasm/src/wasm.rs +++ b/src/components/contracts/primitives/wasm/src/wasm.rs @@ -3,14 +3,15 @@ use core::fmt::Display; use ethereum::{ LegacyTransactionMessage, TransactionSignature, TransactionV0 as LegacyTransaction, - TransactionV2, + TransactionV2 as Transaction, }; use ethereum_types::{H160, H256}; +use serde::{Deserialize, Serialize}; use fp_types::{ - actions::{ethereum::Action2 as EthAction2, Action2}, - assemble::UncheckedTransaction2, - crypto::secp256k1_ecdsa_recover, + actions::{evm, template, xhub}, + crypto::{secp256k1_ecdsa_recover, Address, Signature}, + transaction, }; use fp_utils::tx::EvmRawTxWrapper; use ruc::{d, err::RucResult}; @@ -20,6 +21,22 @@ use wasm_bindgen::prelude::*; use baseapp::BaseApp; use fp_traits::evm::FeeCalculator; +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub enum EthAction { + Transact(Transaction), +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +pub enum Action { + Ethereum(EthAction), + Evm(evm::Action), + XHub(xhub::Action), + Template(template::Action), +} + +pub type UncheckedTransaction = + transaction::UncheckedTransaction; + #[inline(always)] pub(crate) fn error_to_jsvalue(e: T) -> JsValue { JsValue::from_str(&e.to_string()) @@ -36,7 +53,7 @@ pub fn recover_signer(transaction: &LegacyTransaction) -> Option { let pubkey = secp256k1_ecdsa_recover(&sig, &msg).ok()?; Some(H160::from(H256::from_slice( - Keccak256::digest(&pubkey).as_slice(), + Keccak256::digest(pubkey).as_slice(), ))) } @@ -49,10 +66,10 @@ pub fn recover_tx_signer(raw_tx: String) -> Result { .c(d!()) .map_err(error_to_jsvalue)?; - let unchecked_tx: UncheckedTransaction2<()> = serde_json::from_slice(raw_tx) + let unchecked_tx: UncheckedTransaction<()> = serde_json::from_slice(raw_tx) .c(d!()) .map_err(error_to_jsvalue)?; - if let Action2::Ethereum(EthAction2::Transact(tx)) = unchecked_tx.function { + if let Action::Ethereum(EthAction::Transact(tx)) = unchecked_tx.function { let tx = match new_tx2legcay_tx(tx) { Some(tx) => tx, None => return Err(error_to_jsvalue("invalid raw tx")), @@ -73,10 +90,10 @@ pub fn evm_tx_hash(raw_tx: String) -> Result { .c(d!()) .map_err(error_to_jsvalue)?; - let unchecked_tx: UncheckedTransaction2<()> = serde_json::from_slice(raw_tx) + let unchecked_tx: UncheckedTransaction<()> = serde_json::from_slice(raw_tx) .c(d!()) .map_err(error_to_jsvalue)?; - if let Action2::Ethereum(EthAction2::Transact(tx)) = unchecked_tx.function { + if let Action::Ethereum(EthAction::Transact(tx)) = unchecked_tx.function { let tx = match new_tx2legcay_tx(tx) { Some(tx) => tx, None => return Err(error_to_jsvalue("invalid raw tx")), @@ -88,7 +105,7 @@ pub fn evm_tx_hash(raw_tx: String) -> Result { } } -fn new_tx2legcay_tx(tx: TransactionV2) -> Option { +fn new_tx2legcay_tx(tx: Transaction) -> Option { let transaction: LegacyTransaction = match tx { ethereum::TransactionV2::Legacy(tx) => tx, ethereum::TransactionV2::EIP1559(tx) => { @@ -130,13 +147,13 @@ mod test { fn recover_signer_works() { let raw_tx = String::from("eyJzaWduYXR1cmUiOm51bGwsImZ1bmN0aW9uIjp7IkV0aGVyZXVtIjp7IlRyYW5zYWN0Ijp7IkxlZ2FjeSI6eyJub25jZSI6IjB4MCIsImdhc19wcmljZSI6IjB4MjU0MGJlNDAwIiwiZ2FzX2xpbWl0IjoiMHgxMDAwMDAiLCJhY3Rpb24iOnsiQ2FsbCI6IjB4MzMyNWE3ODQyNWYxN2E3ZTQ4N2ViNTY2NmIyYmZkOTNhYmIwNmM3MCJ9LCJ2YWx1ZSI6IjB4YSIsImlucHV0IjpbXSwic2lnbmF0dXJlIjp7InYiOjQzNDAsInIiOiIweDZiMjBjNzIzNTEzOTk4ZThmYTQ4NWM1MmI4ZjlhZTRmZDdiMWUwYmQwZGZiNzk4NTIzMThiMGMxMDBlOTFmNWUiLCJzIjoiMHg0ZDRjOGMxZjJlMTdjMDJjNGE4OTZlMjYyMTI3YjhiZDZlYmZkNWY1YTc1NWEzZTkyMjBjZmM2OGI4YzY5ZDVkIn19fX19fQ=="); let tx_bytes = base64::decode_config(raw_tx, base64::URL_SAFE).unwrap(); - let unchecked_tx: UncheckedTransaction2<()> = + let unchecked_tx: UncheckedTransaction<()> = serde_json::from_slice(tx_bytes.as_slice()).unwrap(); - if let Action2::Ethereum(EthAction2::Transact(tx)) = unchecked_tx.function { + if let Action::Ethereum(EthAction::Transact(tx)) = unchecked_tx.function { let tx: LegacyTransaction = new_tx2legcay_tx(tx).unwrap(); let signer = recover_signer(&tx).unwrap(); assert_eq!( - format!("{:?}", signer), + format!("{signer:?}"), "0x5050a4f4b3f9338c3472dcc01a87c76a144b3c9c" ); } else { @@ -148,13 +165,13 @@ mod test { fn evm_tx_hash_works() { let raw_tx = String::from("eyJzaWduYXR1cmUiOm51bGwsImZ1bmN0aW9uIjp7IkV0aGVyZXVtIjp7IlRyYW5zYWN0Ijp7IkxlZ2FjeSI6eyJub25jZSI6IjB4MCIsImdhc19wcmljZSI6IjB4MjU0MGJlNDAwIiwiZ2FzX2xpbWl0IjoiMHgxMDAwMDAiLCJhY3Rpb24iOnsiQ2FsbCI6IjB4MzMyNWE3ODQyNWYxN2E3ZTQ4N2ViNTY2NmIyYmZkOTNhYmIwNmM3MCJ9LCJ2YWx1ZSI6IjB4YSIsImlucHV0IjpbXSwic2lnbmF0dXJlIjp7InYiOjQzNDAsInIiOiIweDZiMjBjNzIzNTEzOTk4ZThmYTQ4NWM1MmI4ZjlhZTRmZDdiMWUwYmQwZGZiNzk4NTIzMThiMGMxMDBlOTFmNWUiLCJzIjoiMHg0ZDRjOGMxZjJlMTdjMDJjNGE4OTZlMjYyMTI3YjhiZDZlYmZkNWY1YTc1NWEzZTkyMjBjZmM2OGI4YzY5ZDVkIn19fX19fQ=="); let tx_bytes = base64::decode_config(raw_tx, base64::URL_SAFE).unwrap(); - let unchecked_tx: UncheckedTransaction2<()> = + let unchecked_tx: UncheckedTransaction<()> = serde_json::from_slice(tx_bytes.as_slice()).unwrap(); - if let Action2::Ethereum(EthAction2::Transact(tx)) = unchecked_tx.function { + if let Action::Ethereum(EthAction::Transact(tx)) = unchecked_tx.function { let tx: LegacyTransaction = new_tx2legcay_tx(tx).unwrap(); let hash = H256::from_slice(Keccak256::digest(&rlp::encode(&tx)).as_slice()); assert_eq!( - format!("{:?}", hash), + format!("{hash:?}"), "0x83901d025accca27ee53fdf1ee354f4437418731e0995ee031beb99499405d26" ); } else {