mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-06-13 01:41:00 +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
|
# polkadot-sdk and friends
|
||||||
codec = { version = "3.6.12", default-features = false, package = "parity-scale-codec" }
|
codec = { version = "3.6.12", default-features = false, package = "parity-scale-codec" }
|
||||||
scale-info = { version = "2.11.1", default-features = false }
|
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
|
# llvm
|
||||||
[workspace.dependencies.inkwell]
|
[workspace.dependencies.inkwell]
|
||||||
|
|||||||
@@ -14,4 +14,16 @@ contract ExtCode {
|
|||||||
ret := codesize()
|
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 ExtCodeSize(address who) public view returns (uint ret);
|
||||||
|
|
||||||
function CodeSize() public pure 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, ExtCodeSizeCall, ext_code_size, address: Address);
|
||||||
case!("ExtCode.sol", ExtCode, CodeSizeCall, code_size,);
|
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!(
|
sol!(
|
||||||
contract MCopy {
|
contract MCopy {
|
||||||
|
|||||||
@@ -234,6 +234,92 @@ fn signed_remainder() {
|
|||||||
run_differential(actions);
|
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.
|
// These test were implement for the mock-runtime and need to be ported yet.
|
||||||
|
|
||||||
|
|||||||
@@ -49,11 +49,31 @@ where
|
|||||||
|
|
||||||
/// Translates the `extcodehash` instruction.
|
/// Translates the `extcodehash` instruction.
|
||||||
pub fn hash<'ctx, D>(
|
pub fn hash<'ctx, D>(
|
||||||
_context: &mut Context<'ctx, D>,
|
context: &mut Context<'ctx, D>,
|
||||||
_address: inkwell::values::IntValue<'ctx>,
|
address: inkwell::values::IntValue<'ctx>,
|
||||||
) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>>
|
) -> anyhow::Result<inkwell::values::BasicValueEnum<'ctx>>
|
||||||
where
|
where
|
||||||
D: Dependency + Clone,
|
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},
|
pallet_revive::{CollectEvents, ContractExecResult, ContractInstantiateResult, DebugInfo},
|
||||||
polkadot_runtime_common::BuildStorage,
|
polkadot_runtime_common::BuildStorage,
|
||||||
polkadot_sdk_frame::testing_prelude::*,
|
polkadot_sdk_frame::testing_prelude::*,
|
||||||
sp_core::H160,
|
sp_core::{H160, H256},
|
||||||
sp_keystore::{testing::MemoryKeystore, KeystoreExt},
|
sp_keystore::{testing::MemoryKeystore, KeystoreExt},
|
||||||
sp_runtime::AccountId32,
|
sp_runtime::AccountId32,
|
||||||
};
|
};
|
||||||
@@ -185,6 +185,7 @@ pub enum CallResult {
|
|||||||
Instantiate {
|
Instantiate {
|
||||||
result: ContractInstantiateResult<Balance, EventRecord>,
|
result: ContractInstantiateResult<Balance, EventRecord>,
|
||||||
wall_time: Duration,
|
wall_time: Duration,
|
||||||
|
code_hash: H256,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use pallet_revive::AddressMapper;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use alloy_primitives::Address;
|
use alloy_primitives::{keccak256, Address};
|
||||||
#[cfg(feature = "revive-solidity")]
|
#[cfg(feature = "revive-solidity")]
|
||||||
use revive_differential::{Evm, EvmLog};
|
use revive_differential::{Evm, EvmLog};
|
||||||
#[cfg(feature = "revive-solidity")]
|
#[cfg(feature = "revive-solidity")]
|
||||||
@@ -409,6 +409,13 @@ impl Specs {
|
|||||||
data,
|
data,
|
||||||
salt,
|
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 origin = RuntimeOrigin::signed(origin.to_account_id(&results));
|
||||||
let time_start = Instant::now();
|
let time_start = Instant::now();
|
||||||
let result = Contracts::bare_instantiate(
|
let result = Contracts::bare_instantiate(
|
||||||
@@ -416,7 +423,7 @@ impl Specs {
|
|||||||
value,
|
value,
|
||||||
gas_limit.unwrap_or(GAS_LIMIT),
|
gas_limit.unwrap_or(GAS_LIMIT),
|
||||||
storage_deposit_limit.unwrap_or(DEPOSIT_LIMIT),
|
storage_deposit_limit.unwrap_or(DEPOSIT_LIMIT),
|
||||||
code.into(),
|
code,
|
||||||
data,
|
data,
|
||||||
salt.0,
|
salt.0,
|
||||||
DebugInfo::Skip,
|
DebugInfo::Skip,
|
||||||
@@ -425,6 +432,7 @@ impl Specs {
|
|||||||
results.push(CallResult::Instantiate {
|
results.push(CallResult::Instantiate {
|
||||||
result,
|
result,
|
||||||
wall_time: time_start.elapsed(),
|
wall_time: time_start.elapsed(),
|
||||||
|
code_hash,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Upload {
|
Upload {
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ POLKAVM_IMPORT(void, chain_id, uint32_t)
|
|||||||
|
|
||||||
POLKAVM_IMPORT(uint32_t, code_size, 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, deposit_event, uint32_t, uint32_t, uint32_t, uint32_t)
|
||||||
|
|
||||||
POLKAVM_IMPORT(void, get_immutable_data, 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_SIZE: &str = "code_size";
|
||||||
|
|
||||||
|
pub static CODE_HASH: &str = "code_hash";
|
||||||
|
|
||||||
pub static DEPOSIT_EVENT: &str = "deposit_event";
|
pub static DEPOSIT_EVENT: &str = "deposit_event";
|
||||||
|
|
||||||
pub static GET_IMMUTABLE_DATA: &str = "get_immutable_data";
|
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.
|
/// All imported runtime API symbols.
|
||||||
/// Useful for configuring common attributes and linkage.
|
/// Useful for configuring common attributes and linkage.
|
||||||
pub static IMPORTS: [&str; 23] = [
|
pub static IMPORTS: [&str; 24] = [
|
||||||
SBRK,
|
SBRK,
|
||||||
MEMORY_SIZE,
|
MEMORY_SIZE,
|
||||||
ADDRESS,
|
ADDRESS,
|
||||||
@@ -69,6 +71,7 @@ pub static IMPORTS: [&str; 23] = [
|
|||||||
CALLER,
|
CALLER,
|
||||||
CHAIN_ID,
|
CHAIN_ID,
|
||||||
CODE_SIZE,
|
CODE_SIZE,
|
||||||
|
CODE_HASH,
|
||||||
DEPOSIT_EVENT,
|
DEPOSIT_EVENT,
|
||||||
GET_IMMUTABLE_DATA,
|
GET_IMMUTABLE_DATA,
|
||||||
GET_STORAGE,
|
GET_STORAGE,
|
||||||
|
|||||||
Reference in New Issue
Block a user