From 0a7cebe316c4dea69cd619908246ae13816adfc8 Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Tue, 6 Feb 2018 13:57:29 +0300 Subject: [PATCH] adjust storage update evm-style (#7812) --- ethcore/res/wasm-tests | 2 +- ethcore/wasm/src/runtime.rs | 14 +++++++++-- ethcore/wasm/src/tests.rs | 47 +++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/ethcore/res/wasm-tests b/ethcore/res/wasm-tests index ff8504a7f..fb111c82d 160000 --- a/ethcore/res/wasm-tests +++ b/ethcore/res/wasm-tests @@ -1 +1 @@ -Subproject commit ff8504a7f3b3fe78af47fa4e0c24e4a75a7306fd +Subproject commit fb111c82deff8759f54a5038d07cecc77cb5a663 diff --git a/ethcore/wasm/src/runtime.rs b/ethcore/wasm/src/runtime.rs index fa31d851f..1a1c59b9a 100644 --- a/ethcore/wasm/src/runtime.rs +++ b/ethcore/wasm/src/runtime.rs @@ -218,11 +218,21 @@ impl<'a> Runtime<'a> { let key = self.h256_at(args.nth(0)?)?; let val_ptr: u32 = args.nth(1)?; - self.adjusted_charge(|schedule| schedule.sstore_set_gas as u64)?; - let val = self.h256_at(val_ptr)?; + let former_val = self.ext.storage_at(&key).map_err(|_| Error::StorageUpdateError)?; + + if former_val == H256::zero() && val != H256::zero() { + self.adjusted_charge(|schedule| schedule.sstore_set_gas as u64)?; + } else { + self.adjusted_charge(|schedule| schedule.sstore_reset_gas as u64)?; + } + self.ext.set_storage(key, val).map_err(|_| Error::StorageUpdateError)?; + if former_val != H256::zero() && val == H256::zero() { + self.ext.inc_sstore_clears(); + } + Ok(()) } diff --git a/ethcore/wasm/src/tests.rs b/ethcore/wasm/src/tests.rs index 244c3b4dd..84ef28339 100644 --- a/ethcore/wasm/src/tests.rs +++ b/ethcore/wasm/src/tests.rs @@ -659,6 +659,53 @@ fn math_div() { assert_eq!(gas_left, U256::from(90_607)); } +#[test] +fn storage_metering() { + ::ethcore_logger::init_log(); + + // #1 + let mut ext = FakeExt::new(); + + let code = Arc::new(load_sample!("setter.wasm")); + let address: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap(); + + let mut params = ActionParams::default(); + params.address = address.clone(); + params.gas = U256::from(100_000); + params.code = Some(code.clone()); + params.data = Some(vec![ + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, + ]); + + let gas_left = { + let mut interpreter = wasm_interpreter(); + test_finalize(interpreter.exec(params, &mut ext)).unwrap() + }; + + // 0 -> not 0 + assert_eq!(gas_left, U256::from(74_410)); + + // #2 + + let mut params = ActionParams::default(); + params.address = address.clone(); + params.gas = U256::from(100_000); + params.code = Some(code.clone()); + params.data = Some(vec![ + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x6b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, + ]); + + let gas_left = { + let mut interpreter = wasm_interpreter(); + test_finalize(interpreter.exec(params, &mut ext)).unwrap() + }; + + // not 0 -> not 0 + assert_eq!(gas_left, U256::from(89_410)); +} + // This test checks the ability of wasm contract to invoke // varios blockchain runtime methods #[test]