mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-04-22 06:48:03 +00:00
Implement extcodehash (#77)
This commit is contained in:
Generated
+436
-469
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -67,7 +67,7 @@ log = { version = "0.4" }
|
||||
# polkadot-sdk and friends
|
||||
codec = { version = "3.6.12", default-features = false, package = "parity-scale-codec" }
|
||||
scale-info = { version = "2.11.1", default-features = false }
|
||||
polkadot-sdk = { git = "https://github.com/paritytech/polkadot-sdk", rev = "5f55185eac6b4366484cf1bd7d374b2e652b076a" }
|
||||
polkadot-sdk = { git = "https://github.com/paritytech/polkadot-sdk", rev = "5e0843e5a0fb601016dc1ccd46451a96049600e9" }
|
||||
|
||||
# llvm
|
||||
[workspace.dependencies.inkwell]
|
||||
|
||||
@@ -14,4 +14,16 @@ contract ExtCode {
|
||||
ret := codesize()
|
||||
}
|
||||
}
|
||||
|
||||
function ExtCodeHash(address who) public view returns (bytes32 ret) {
|
||||
assembly {
|
||||
ret := extcodehash(who)
|
||||
}
|
||||
}
|
||||
|
||||
function CodeHash() public view returns (bytes32 ret) {
|
||||
assembly {
|
||||
ret := extcodehash(address())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,10 +178,16 @@ sol!(
|
||||
function ExtCodeSize(address who) public view returns (uint ret);
|
||||
|
||||
function CodeSize() public pure returns (uint ret);
|
||||
|
||||
function ExtCodeHash(address who) public view returns (bytes32 ret);
|
||||
|
||||
function CodeHash() public view returns (bytes32 ret);
|
||||
}
|
||||
);
|
||||
case!("ExtCode.sol", ExtCode, ExtCodeSizeCall, ext_code_size, address: Address);
|
||||
case!("ExtCode.sol", ExtCode, CodeSizeCall, code_size,);
|
||||
case!("ExtCode.sol", ExtCode, ExtCodeHashCall, ext_code_hash, address: Address);
|
||||
case!("ExtCode.sol", ExtCode, CodeHashCall, code_hash,);
|
||||
|
||||
sol!(
|
||||
contract MCopy {
|
||||
|
||||
@@ -234,6 +234,92 @@ fn signed_remainder() {
|
||||
run_differential(actions);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ext_code_hash() {
|
||||
let mut actions = instantiate("contracts/ExtCode.sol", "ExtCode");
|
||||
|
||||
// First do contract instantiation to figure out address and code hash
|
||||
let results = Specs {
|
||||
actions: actions.clone(),
|
||||
..Default::default()
|
||||
}
|
||||
.run();
|
||||
let (addr, code_hash) = match results.first().cloned() {
|
||||
Some(CallResult::Instantiate {
|
||||
result, code_hash, ..
|
||||
}) => (result.result.unwrap().addr, code_hash),
|
||||
_ => panic!("instantiate contract failed"),
|
||||
};
|
||||
|
||||
// code hash of itself
|
||||
actions.push(Call {
|
||||
origin: TestAddress::Alice,
|
||||
dest: TestAddress::Instantiated(0),
|
||||
value: 0,
|
||||
gas_limit: None,
|
||||
storage_deposit_limit: None,
|
||||
data: Contract::code_hash().calldata,
|
||||
});
|
||||
actions.push(VerifyCall(VerifyCallExpectation {
|
||||
success: true,
|
||||
output: OptionalHex::from(code_hash.as_bytes().to_vec()),
|
||||
gas_consumed: None,
|
||||
}));
|
||||
|
||||
// code hash for a given contract address
|
||||
actions.push(Call {
|
||||
origin: TestAddress::Alice,
|
||||
dest: TestAddress::Instantiated(0),
|
||||
value: 0,
|
||||
gas_limit: None,
|
||||
storage_deposit_limit: None,
|
||||
data: Contract::ext_code_hash(Address::from(addr.to_fixed_bytes())).calldata,
|
||||
});
|
||||
actions.push(VerifyCall(VerifyCallExpectation {
|
||||
success: true,
|
||||
output: OptionalHex::from(code_hash.as_bytes().to_vec()),
|
||||
gas_consumed: None,
|
||||
}));
|
||||
|
||||
// EOA returns fixed hash
|
||||
actions.push(Call {
|
||||
origin: TestAddress::Alice,
|
||||
dest: TestAddress::Instantiated(0),
|
||||
value: 0,
|
||||
gas_limit: None,
|
||||
storage_deposit_limit: None,
|
||||
data: Contract::ext_code_hash(Address::from(CHARLIE.to_fixed_bytes())).calldata,
|
||||
});
|
||||
actions.push(VerifyCall(VerifyCallExpectation {
|
||||
success: true,
|
||||
output: OptionalHex::from(
|
||||
hex!("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470").to_vec(),
|
||||
),
|
||||
gas_consumed: None,
|
||||
}));
|
||||
|
||||
// non-existing account
|
||||
actions.push(Call {
|
||||
origin: TestAddress::Alice,
|
||||
dest: TestAddress::Instantiated(0),
|
||||
value: 0,
|
||||
gas_limit: None,
|
||||
storage_deposit_limit: None,
|
||||
data: Contract::ext_code_hash(Address::from([8u8; 20])).calldata,
|
||||
});
|
||||
actions.push(VerifyCall(VerifyCallExpectation {
|
||||
success: true,
|
||||
output: OptionalHex::from([0u8; 32].to_vec()),
|
||||
gas_consumed: None,
|
||||
}));
|
||||
|
||||
Specs {
|
||||
actions,
|
||||
..Default::default()
|
||||
}
|
||||
.run();
|
||||
}
|
||||
|
||||
/*
|
||||
// These test were implement for the mock-runtime and need to be ported yet.
|
||||
|
||||
|
||||
@@ -49,11 +49,31 @@ where
|
||||
|
||||
/// Translates the `extcodehash` instruction.
|
||||
pub fn hash<'ctx, D>(
|
||||
_context: &mut Context<'ctx, D>,
|
||||
_address: inkwell::values::IntValue<'ctx>,
|
||||
context: &mut Context<'ctx, D>,
|
||||
address: inkwell::values::IntValue<'ctx>,
|
||||
) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>>
|
||||
where
|
||||
D: Dependency + Clone,
|
||||
{
|
||||
todo!()
|
||||
let address_type = context.integer_type(revive_common::BIT_LENGTH_ETH_ADDRESS);
|
||||
let address_pointer = context.build_alloca_at_entry(address_type, "address_pointer");
|
||||
let address_truncated =
|
||||
context
|
||||
.builder()
|
||||
.build_int_truncate(address, address_type, "address_truncated")?;
|
||||
let address_swapped = context.build_byte_swap(address_truncated.into())?;
|
||||
context.build_store(address_pointer, address_swapped)?;
|
||||
|
||||
let extcodehash_pointer =
|
||||
context.build_alloca_at_entry(context.word_type(), "extcodehash_pointer");
|
||||
|
||||
context.build_runtime_call(
|
||||
revive_runtime_api::polkavm_imports::CODE_HASH,
|
||||
&[
|
||||
address_pointer.to_int(context).into(),
|
||||
extcodehash_pointer.to_int(context).into(),
|
||||
],
|
||||
);
|
||||
|
||||
context.build_byte_swap(context.build_load(extcodehash_pointer, "extcodehash_value")?)
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ use polkadot_sdk::{
|
||||
pallet_revive::{CollectEvents, ContractExecResult, ContractInstantiateResult, DebugInfo},
|
||||
polkadot_runtime_common::BuildStorage,
|
||||
polkadot_sdk_frame::testing_prelude::*,
|
||||
sp_core::H160,
|
||||
sp_core::{H160, H256},
|
||||
sp_keystore::{testing::MemoryKeystore, KeystoreExt},
|
||||
sp_runtime::AccountId32,
|
||||
};
|
||||
@@ -185,6 +185,7 @@ pub enum CallResult {
|
||||
Instantiate {
|
||||
result: ContractInstantiateResult<Balance, EventRecord>,
|
||||
wall_time: Duration,
|
||||
code_hash: H256,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ use pallet_revive::AddressMapper;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::*;
|
||||
use alloy_primitives::Address;
|
||||
use alloy_primitives::{keccak256, Address};
|
||||
#[cfg(feature = "revive-solidity")]
|
||||
use revive_differential::{Evm, EvmLog};
|
||||
#[cfg(feature = "revive-solidity")]
|
||||
@@ -409,6 +409,13 @@ impl Specs {
|
||||
data,
|
||||
salt,
|
||||
} => {
|
||||
let code: pallet_revive::Code = code.into();
|
||||
let code_hash = match code.clone() {
|
||||
pallet_revive::Code::Existing(code_hash) => code_hash,
|
||||
pallet_revive::Code::Upload(bytes) => {
|
||||
H256::from_slice(keccak256(&bytes).as_slice())
|
||||
}
|
||||
};
|
||||
let origin = RuntimeOrigin::signed(origin.to_account_id(&results));
|
||||
let time_start = Instant::now();
|
||||
let result = Contracts::bare_instantiate(
|
||||
@@ -416,7 +423,7 @@ impl Specs {
|
||||
value,
|
||||
gas_limit.unwrap_or(GAS_LIMIT),
|
||||
storage_deposit_limit.unwrap_or(DEPOSIT_LIMIT),
|
||||
code.into(),
|
||||
code,
|
||||
data,
|
||||
salt.0,
|
||||
DebugInfo::Skip,
|
||||
@@ -425,6 +432,7 @@ impl Specs {
|
||||
results.push(CallResult::Instantiate {
|
||||
result,
|
||||
wall_time: time_start.elapsed(),
|
||||
code_hash,
|
||||
})
|
||||
}
|
||||
Upload {
|
||||
|
||||
@@ -80,6 +80,8 @@ POLKAVM_IMPORT(void, chain_id, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(uint32_t, code_size, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(void, code_hash, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(void, deposit_event, uint32_t, uint32_t, uint32_t, uint32_t)
|
||||
|
||||
POLKAVM_IMPORT(void, get_immutable_data, uint32_t, uint32_t);
|
||||
|
||||
@@ -30,6 +30,8 @@ pub static CHAIN_ID: &str = "chain_id";
|
||||
|
||||
pub static CODE_SIZE: &str = "code_size";
|
||||
|
||||
pub static CODE_HASH: &str = "code_hash";
|
||||
|
||||
pub static DEPOSIT_EVENT: &str = "deposit_event";
|
||||
|
||||
pub static GET_IMMUTABLE_DATA: &str = "get_immutable_data";
|
||||
@@ -58,7 +60,7 @@ pub static VALUE_TRANSFERRED: &str = "value_transferred";
|
||||
|
||||
/// All imported runtime API symbols.
|
||||
/// Useful for configuring common attributes and linkage.
|
||||
pub static IMPORTS: [&str; 23] = [
|
||||
pub static IMPORTS: [&str; 24] = [
|
||||
SBRK,
|
||||
MEMORY_SIZE,
|
||||
ADDRESS,
|
||||
@@ -69,6 +71,7 @@ pub static IMPORTS: [&str; 23] = [
|
||||
CALLER,
|
||||
CHAIN_ID,
|
||||
CODE_SIZE,
|
||||
CODE_HASH,
|
||||
DEPOSIT_EVENT,
|
||||
GET_IMMUTABLE_DATA,
|
||||
GET_STORAGE,
|
||||
|
||||
Reference in New Issue
Block a user