mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-06-13 11:51:06 +00:00
implement the code size opcodes (#107)
This commit is contained in:
Generated
+357
-357
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 = "db40a66db71e8e7fe943dda5cd0e28078efa2a19" }
|
polkadot-sdk = { git = "https://github.com/paritytech/polkadot-sdk", rev = "2b6b69641ccff4d7aa9c32051bbb2f1e775ef8cc" }
|
||||||
|
|
||||||
# llvm
|
# llvm
|
||||||
[workspace.dependencies.inkwell]
|
[workspace.dependencies.inkwell]
|
||||||
|
|||||||
@@ -105,9 +105,7 @@ contract ERC20Tester {
|
|||||||
ERC20 token = new ERC20();
|
ERC20 token = new ERC20();
|
||||||
assert(token.decimals() == 18);
|
assert(token.decimals() == 18);
|
||||||
|
|
||||||
// use call directly when code_size is implemented on pallet-revive
|
token.mint(300);
|
||||||
|
|
||||||
address(token).call(abi.encodeWithSignature("mint(uint256)", 300));
|
|
||||||
assert(token.balanceOf(address(this)) == 300);
|
assert(token.balanceOf(address(this)) == 300);
|
||||||
token.transfer(BOB, 100);
|
token.transfer(BOB, 100);
|
||||||
assert(token.balanceOf(address(this)) == 200);
|
assert(token.balanceOf(address(this)) == 200);
|
||||||
@@ -119,7 +117,7 @@ contract ERC20Tester {
|
|||||||
assert(token.balanceOf(BOB) == 200);
|
assert(token.balanceOf(BOB) == 200);
|
||||||
assert(token.balanceOf(address(this)) == 100);
|
assert(token.balanceOf(address(this)) == 100);
|
||||||
|
|
||||||
address(token).call(abi.encodeWithSignature("burn(uint256)", 100));
|
token.burn(100);
|
||||||
assert(token.balanceOf(address(this)) == 0);
|
assert(token.balanceOf(address(this)) == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+108
-24
@@ -321,6 +321,114 @@ fn ext_code_hash() {
|
|||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn ext_code_size() {
|
||||||
|
let alice = Address::from(ALICE.0);
|
||||||
|
let own_address = alice.create(0);
|
||||||
|
let baseline_address = alice.create2([0u8; 32], keccak256(Contract::baseline().pvm_runtime));
|
||||||
|
|
||||||
|
let own_code_size = U256::from(
|
||||||
|
Contract::ext_code_size(Default::default())
|
||||||
|
.pvm_runtime
|
||||||
|
.len(),
|
||||||
|
);
|
||||||
|
let baseline_code_size = U256::from(Contract::baseline().pvm_runtime.len());
|
||||||
|
|
||||||
|
Specs {
|
||||||
|
actions: vec![
|
||||||
|
// Instantiate the test contract
|
||||||
|
instantiate("contracts/ExtCode.sol", "ExtCode").remove(0),
|
||||||
|
// Instantiate the baseline contract
|
||||||
|
Instantiate {
|
||||||
|
origin: TestAddress::Alice,
|
||||||
|
value: 0,
|
||||||
|
gas_limit: Some(GAS_LIMIT),
|
||||||
|
storage_deposit_limit: None,
|
||||||
|
code: Code::Solidity {
|
||||||
|
path: Some("contracts/Baseline.sol".into()),
|
||||||
|
contract: "Baseline".to_string(),
|
||||||
|
solc_optimizer: None,
|
||||||
|
pipeline: None,
|
||||||
|
},
|
||||||
|
data: vec![],
|
||||||
|
salt: OptionalHex::from([0; 32]),
|
||||||
|
},
|
||||||
|
// Alice is not a contract and returns a code size of 0
|
||||||
|
Call {
|
||||||
|
origin: TestAddress::Alice,
|
||||||
|
dest: TestAddress::Instantiated(0),
|
||||||
|
value: 0,
|
||||||
|
gas_limit: None,
|
||||||
|
storage_deposit_limit: None,
|
||||||
|
data: Contract::ext_code_size(alice).calldata,
|
||||||
|
},
|
||||||
|
VerifyCall(VerifyCallExpectation {
|
||||||
|
success: true,
|
||||||
|
output: OptionalHex::from([0u8; 32].to_vec()),
|
||||||
|
gas_consumed: None,
|
||||||
|
}),
|
||||||
|
// Unknown address returns a code size of 0
|
||||||
|
Call {
|
||||||
|
origin: TestAddress::Alice,
|
||||||
|
dest: TestAddress::Instantiated(0),
|
||||||
|
value: 0,
|
||||||
|
gas_limit: None,
|
||||||
|
storage_deposit_limit: None,
|
||||||
|
data: Contract::ext_code_size(Address::from([0xff; 20])).calldata,
|
||||||
|
},
|
||||||
|
VerifyCall(VerifyCallExpectation {
|
||||||
|
success: true,
|
||||||
|
output: OptionalHex::from([0u8; 32].to_vec()),
|
||||||
|
gas_consumed: None,
|
||||||
|
}),
|
||||||
|
// Own address via extcodesize returns own code size
|
||||||
|
Call {
|
||||||
|
origin: TestAddress::Alice,
|
||||||
|
dest: TestAddress::Instantiated(0),
|
||||||
|
value: 0,
|
||||||
|
gas_limit: None,
|
||||||
|
storage_deposit_limit: None,
|
||||||
|
data: Contract::ext_code_size(own_address).calldata,
|
||||||
|
},
|
||||||
|
VerifyCall(VerifyCallExpectation {
|
||||||
|
success: true,
|
||||||
|
output: OptionalHex::from(own_code_size.to_be_bytes::<32>().to_vec()),
|
||||||
|
gas_consumed: None,
|
||||||
|
}),
|
||||||
|
// Own address via codesize returns own code size
|
||||||
|
Call {
|
||||||
|
origin: TestAddress::Alice,
|
||||||
|
dest: TestAddress::Instantiated(0),
|
||||||
|
value: 0,
|
||||||
|
gas_limit: None,
|
||||||
|
storage_deposit_limit: None,
|
||||||
|
data: Contract::code_size().calldata,
|
||||||
|
},
|
||||||
|
VerifyCall(VerifyCallExpectation {
|
||||||
|
success: true,
|
||||||
|
output: OptionalHex::from(own_code_size.to_be_bytes::<32>().to_vec()),
|
||||||
|
gas_consumed: None,
|
||||||
|
}),
|
||||||
|
// Baseline address returns the baseline code size
|
||||||
|
Call {
|
||||||
|
origin: TestAddress::Alice,
|
||||||
|
dest: TestAddress::Instantiated(0),
|
||||||
|
value: 0,
|
||||||
|
gas_limit: None,
|
||||||
|
storage_deposit_limit: None,
|
||||||
|
data: Contract::ext_code_size(baseline_address).calldata,
|
||||||
|
},
|
||||||
|
VerifyCall(VerifyCallExpectation {
|
||||||
|
success: true,
|
||||||
|
output: OptionalHex::from(baseline_code_size.to_be_bytes::<32>().to_vec()),
|
||||||
|
gas_consumed: None,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
..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.
|
||||||
|
|
||||||
@@ -349,28 +457,4 @@ fn create2_failure() {
|
|||||||
|
|
||||||
assert_eq!(output.flags, ReturnFlags::Revert);
|
assert_eq!(output.flags, ReturnFlags::Revert);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn ext_code_size() {
|
|
||||||
let contract = Contract::ext_code_size(Transaction::default_address());
|
|
||||||
let (_, output) = assert_success(&contract, false);
|
|
||||||
let received = U256::from_be_slice(&output.data);
|
|
||||||
let expected = U256::from(contract.pvm_runtime.len());
|
|
||||||
assert_eq!(received, expected);
|
|
||||||
|
|
||||||
let contract = Contract::ext_code_size(Default::default());
|
|
||||||
let (_, output) = assert_success(&contract, false);
|
|
||||||
let received = U256::from_be_slice(&output.data);
|
|
||||||
let expected = U256::ZERO;
|
|
||||||
assert_eq!(received, expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn code_size() {
|
|
||||||
let contract = Contract::code_size();
|
|
||||||
let (_, output) = assert_success(&contract, false);
|
|
||||||
let expected = U256::from(contract.pvm_runtime.len());
|
|
||||||
let received = U256::from_be_slice(&output.data);
|
|
||||||
assert_eq!(expected, received);
|
|
||||||
}
|
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
//! Translates the external code operations.
|
//! Translates the external code operations.
|
||||||
|
|
||||||
use inkwell::values::BasicValue;
|
|
||||||
|
|
||||||
use crate::polkavm::context::Context;
|
use crate::polkavm::context::Context;
|
||||||
use crate::polkavm::Dependency;
|
use crate::polkavm::Dependency;
|
||||||
|
|
||||||
@@ -14,37 +12,23 @@ pub fn size<'ctx, D>(
|
|||||||
where
|
where
|
||||||
D: Dependency + Clone,
|
D: Dependency + Clone,
|
||||||
{
|
{
|
||||||
let address_pointer = match address {
|
let address = match address {
|
||||||
Some(address) => {
|
Some(address) => address,
|
||||||
let address_pointer = context.build_alloca(context.word_type(), "value");
|
None => super::context::address(context)?.into_int_value(),
|
||||||
context.build_store(address_pointer, address)?;
|
|
||||||
address_pointer
|
|
||||||
}
|
|
||||||
None => context.sentinel_pointer(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let address_pointer_casted = context.builder().build_ptr_to_int(
|
let address_pointer = context.build_address_argument_store(address)?;
|
||||||
address_pointer.value,
|
let output_pointer = context.build_alloca_at_entry(context.word_type(), "output_pointer");
|
||||||
context.xlen_type(),
|
|
||||||
"address_pointer",
|
|
||||||
)?;
|
|
||||||
let value = context
|
|
||||||
.build_runtime_call(
|
|
||||||
revive_runtime_api::polkavm_imports::CODE_SIZE,
|
|
||||||
&[address_pointer_casted.into()],
|
|
||||||
)
|
|
||||||
.unwrap_or_else(|| {
|
|
||||||
panic!(
|
|
||||||
"{} should return a value",
|
|
||||||
revive_runtime_api::polkavm_imports::CODE_SIZE
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.into_int_value();
|
|
||||||
|
|
||||||
Ok(context
|
context.build_runtime_call(
|
||||||
.builder()
|
revive_runtime_api::polkavm_imports::CODE_SIZE,
|
||||||
.build_int_z_extend(value, context.word_type(), "extcodesize")?
|
&[
|
||||||
.as_basic_value_enum())
|
address_pointer.to_int(context).into(),
|
||||||
|
output_pointer.to_int(context).into(),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
context.build_load(output_pointer, "code_size")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Translates the `extcodehash` instruction.
|
/// Translates the `extcodehash` instruction.
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ POLKAVM_IMPORT(void, caller, uint32_t)
|
|||||||
|
|
||||||
POLKAVM_IMPORT(void, chain_id, uint32_t)
|
POLKAVM_IMPORT(void, chain_id, uint32_t)
|
||||||
|
|
||||||
POLKAVM_IMPORT(uint32_t, code_size, uint32_t)
|
POLKAVM_IMPORT(uint32_t, code_size, uint32_t, uint32_t)
|
||||||
|
|
||||||
POLKAVM_IMPORT(void, code_hash, uint32_t, uint32_t)
|
POLKAVM_IMPORT(void, code_hash, uint32_t, uint32_t)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user