Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
107 commits
Select commit Hold shift + click to select a range
8bb5143
decl_module and extract runtime mod
pepyakin Jul 4, 2018
7fa574f
Invert dependency staking←→contract
pepyakin Jul 4, 2018
8c06e98
Remove CodeOf
pepyakin Jul 4, 2018
f315ca0
Remove StorageOf and move double_map
pepyakin Jul 4, 2018
799e591
Comment staking test
pepyakin Jul 4, 2018
92922fd
Clean
pepyakin Jul 4, 2018
d43ab98
Add gas_price and gas_limit
pepyakin Jul 4, 2018
92cfeeb
Commit.
pepyakin Jul 4, 2018
a4264f3
Renames
pepyakin Jul 4, 2018
9d07af9
Params
pepyakin Jul 5, 2018
00919a4
WIP
pepyakin Jul 5, 2018
900c859
Rename transfer to call
pepyakin Jul 6, 2018
593d51c
WIP
pepyakin Jul 11, 2018
0b501c6
Rebuild binaries.
pepyakin Jul 11, 2018
ce0e128
WIP
pepyakin Jul 11, 2018
8915d76
Backport ctro changes
pepyakin Jul 11, 2018
ca48073
Call wiring
pepyakin Jul 12, 2018
3f2423f
Commit overlay.
pepyakin Jul 13, 2018
32b0e55
Rename merge → commit, into_state → ..._change_set
pepyakin Jul 13, 2018
8577fad
WIP
pepyakin Jul 14, 2018
14ee2f4
Contract creation routines
pepyakin Jul 14, 2018
3a218d9
Set code of the created account.
pepyakin Jul 14, 2018
e8157c6
Fix the ID of `create` Call
pepyakin Jul 14, 2018
43508cd
Fix most of the warning.
pepyakin Jul 14, 2018
a4b6480
Add the simplest test in the contract crate
pepyakin Jul 14, 2018
a340742
Transfers work!
pepyakin Jul 14, 2018
e3b906c
Add contract_create test.
pepyakin Jul 14, 2018
8a541a3
Clean
pepyakin Jul 14, 2018
77ee25b
Add top-level create test
pepyakin Jul 14, 2018
30a72d3
Clean a bit.
pepyakin Jul 14, 2018
51ee15d
Pass gas_limit and data via create.
pepyakin Jul 14, 2018
9c1c246
Introduce OnAccountKill callback in staking
pepyakin Jul 14, 2018
3d3a4b7
Hook up OnAccountKill
pepyakin Jul 14, 2018
6ccefe6
Comments
pepyakin Jul 14, 2018
856de95
Pay for gas.
pepyakin Jul 15, 2018
b3c256b
Refund unused gas in call
pepyakin Jul 15, 2018
18a36a3
Tests for zero call and zero endownment.
pepyakin Jul 15, 2018
1872173
Add todo about rewriting docs
pepyakin Jul 15, 2018
8be77ad
Pay for gas in create transactions
pepyakin Jul 15, 2018
0df8491
Fix refunds
pepyakin Jul 15, 2018
25492de
Clean unrelevant comments
pepyakin Jul 15, 2018
f3a2ebf
fixup! Fix refunds
pepyakin Jul 15, 2018
ea2254d
fixup! Clean unrelevant comments
pepyakin Jul 15, 2018
315c0ea
Move DetermineContractAddress to contract
pepyakin Jul 15, 2018
3ab381c
fixup! Clean unrelevant comments
pepyakin Jul 15, 2018
b513597
Inline effect_transfer, remove effect_create
pepyakin Jul 15, 2018
cdb2eeb
Merge 'origin/master' into ser-contract-ioc
pepyakin Jul 15, 2018
d54cec0
Use own new_test_ext.
pepyakin Jul 15, 2018
4032b2f
Don't account for liability
pepyakin Jul 15, 2018
3dfd294
Add some docs
pepyakin Jul 16, 2018
f276d52
Move contract_fee into contract module
pepyakin Jul 16, 2018
42d3fb8
Take GasMeter in vm::execute
pepyakin Jul 16, 2018
75631f6
Use GasMeter throughout contract module for meter
pepyakin Jul 16, 2018
c2bc86d
gas module refactoring
pepyakin Jul 16, 2018
bf07b3c
Clean
pepyakin Jul 16, 2018
952112c
Add base call fee
pepyakin Jul 16, 2018
fa8991e
note about gas price should be taken from storage
pepyakin Jul 16, 2018
3e70be5
Add base fee for create
pepyakin Jul 16, 2018
87c5b12
Rename send → call
pepyakin Jul 16, 2018
f15ac41
Clean
pepyakin Jul 16, 2018
41f33b7
Take fee expressed in dots in gas
pepyakin Jul 16, 2018
cb6e995
Add Checked{Add,Sub,Mul,Div} to SimpleArithmetic
pepyakin Jul 16, 2018
8e5f297
Make Gas generic
pepyakin Jul 16, 2018
b16fec1
Store {call,create}_base_fee in storage
pepyakin Jul 16, 2018
6072034
Clean
pepyakin Jul 16, 2018
5bd0ee9
Rename buy_gas
pepyakin Jul 16, 2018
dadf9d8
Store gas_price in the storage
pepyakin Jul 16, 2018
6c93532
Remove unneeded comment.
pepyakin Jul 16, 2018
b84d090
Bail out if contract already has code.
pepyakin Jul 16, 2018
259a32f
Todos
pepyakin Jul 16, 2018
525df4b
Refund even if top-level contract fails.
pepyakin Jul 16, 2018
8562de6
Fix error msg
pepyakin Jul 16, 2018
4122f48
Fix caller issue
pepyakin Jul 16, 2018
f9497dd
Extract tests module
pepyakin Jul 16, 2018
7bf7759
Add max_depth var in storage
pepyakin Jul 16, 2018
de095a6
Remove left over gas_left
pepyakin Jul 16, 2018
338fe9f
Refactor exec
pepyakin Jul 16, 2018
4377497
Add test oog test.
pepyakin Jul 16, 2018
8ce5aed
set_free_balance_creating
pepyakin Jul 16, 2018
d8fa9e4
Docs and comments.
pepyakin Jul 17, 2018
a1ecfb0
Merge 'origin/master' into ser-contract-ioc
pepyakin Jul 17, 2018
91371c9
Update storage roots because of ContractFee move
pepyakin Jul 17, 2018
4dfc7dc
Rebuild binaries.
pepyakin Jul 17, 2018
2348c18
Simplify vm code.
pepyakin Jul 17, 2018
5873335
Wrapping.
pepyakin Jul 17, 2018
62b498d
Refactor a bit.
pepyakin Jul 17, 2018
895386d
Typo
pepyakin Jul 17, 2018
3e92676
UpdateBalanceOutcome enum
pepyakin Jul 17, 2018
ee97b9e
Style grumbles.
pepyakin Jul 17, 2018
34189ee
Merge 'origin/master' into ser-contract-ioc
pepyakin Jul 17, 2018
a18292a
Rebuild binaries.
pepyakin Jul 17, 2018
81e6eb7
Always consume the given amount of gas.
pepyakin Jul 17, 2018
9a52a44
[skip ci] endownment → endowment
pepyakin Jul 18, 2018
d91dfbe
Rename `AccountId` generic in on_account_kill
pepyakin Jul 23, 2018
ee83701
Merge branch 'master' into ser-contract-ioc
pepyakin Jul 24, 2018
f570351
Fix Cargo.lock
pepyakin Jul 24, 2018
4de767b
Refine docs for gas meter.
pepyakin Jul 24, 2018
58878a8
[skip ci] Add comments for gas module
pepyakin Jul 24, 2018
7a712e1
Merge branch 'master' into ser-contract-ioc
pepyakin Jul 24, 2018
eeebaba
Directly assign to `return_data` at declaration
pepyakin Jul 25, 2018
595e534
Use slices instead of vecs to pass the input data
pepyakin Jul 25, 2018
a846bb1
Add todo about passing return data without copy
pepyakin Jul 25, 2018
3afe59a
Use checked_add instead of add with overflow
pepyakin Jul 25, 2018
dae4d40
Use return_data directly.
pepyakin Jul 25, 2018
9e13c68
Rebuild binaries.
pepyakin Jul 25, 2018
d6c6250
Merge 'origin/master' into ser-contract-ioc
pepyakin Jul 27, 2018
af99a9d
Rebuild binaries.
pepyakin Jul 27, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Transfers work!
  • Loading branch information
pepyakin committed Jul 14, 2018
commit a3407426e317dd8bd5065cddde1d8fac37dd49ac
18 changes: 9 additions & 9 deletions substrate/runtime/contract/src/account_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.

use super::{Trait, StorageOf, CodeOf};
use staking;
use system;
use double_map::StorageDoubleMap;
use runtime_support::StorageMap;
Expand Down Expand Up @@ -57,15 +58,16 @@ impl<T: Trait> AccountDb<T> for DirectAccountDb {
fn get_code(&self, account: &T::AccountId) -> Vec<u8> {
<CodeOf<T>>::get(account)
}
fn get_balance(&self, _account: &T::AccountId) -> T::Balance {
// TODO:
panic!()
fn get_balance(&self, account: &T::AccountId) -> T::Balance {
staking::Module::<T>::free_balance(account)
}
fn commit(&mut self, s: ChangeSet<T>) {
for (address, changed) in s.into_iter() {
if let Some(_balance) = changed.balance {
// TODO:
panic!()
if let Some(balance) = changed.balance {
let still_alive = staking::Module::<T>::commit_free_balance(&address, balance);
if !still_alive {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why a let first instead of putting it into one line?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that is intentional: I think

if set_free_balance(addr, balance) { continue }

is too obscure.

However, I think adding something like

if set_free_balance(addr, balance) == FreeBalanceResult::Killed { continue }

would be much better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

continue
}
}
if let Some(code) = changed.code {
<CodeOf<T>>::insert(&address, &code);
Expand Down Expand Up @@ -152,9 +154,7 @@ impl<'a, T: Trait> AccountDb<T> for OverlayAccountDb<'a, T> {
Entry::Occupied(e) => {
let mut value = e.into_mut();
if changed.balance.is_some() {
// TODO:
panic!();
// value.balance = changed.balance;
value.balance = changed.balance;
}
if changed.code.is_some() {
value.code = changed.code;
Expand Down
66 changes: 54 additions & 12 deletions substrate/runtime/contract/src/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
use super::{CodeOf, ContractAddressFor, Trait};
use account_db::{AccountDb, ChangeSet, OverlayAccountDb};
use rstd::prelude::*;
use runtime_primitives::traits::Zero;
use runtime_support::StorageMap;
use staking;
use system;
use vm;

//pub struct TransactionData {
Expand Down Expand Up @@ -48,7 +51,7 @@ impl<'a, 'b: 'a, T: Trait> ExecutionContext<'a, 'b, T> {
pub fn call(
&mut self,
dest: T::AccountId,
_value: T::Balance,
value: T::Balance,
gas_limit: u64,
_data: Vec<u8>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understood this, we don't pass _data to vm::execute or Ext yet because it's unimplemented, right?

And just a note on quadratic attacks -- it looks like we decide to put callstack directly on program stack, so in the future, using &[u8] might be more efficient and lifetime should work.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, exactly, it is untackled issue right now. And I didn't delve into it.
And yes, in theory, we can directly read from/write to the caller memory.

But there is a complication with writing though. Maybe we will have to make a temporary copy. The reason for that is caller can't know the size of the return buffer before calling the callee, and thus, might want to allocate space after the return data size is known. This is an open research question right now.

) -> Result<vm::ExecutionResult, ()> {
Expand All @@ -57,9 +60,13 @@ impl<'a, 'b: 'a, T: Trait> ExecutionContext<'a, 'b, T> {
// TODO: transfer `_value` using `overlay`. Return an error if failed.
// TODO: check the new depth

let (exec_result, change_set) = if !dest_code.is_empty() {
let (exec_result, change_set) = {
let mut overlay = OverlayAccountDb::new(self.account_db);
let exec_result = {

// TODO: It would be nice to propogate the error.
transfer(&self.self_account, &dest, value, &mut overlay).map_err(|_| ())?;

let exec_result = if !dest_code.is_empty() {
let mut nested = ExecutionContext {
account_db: &mut overlay,
_caller: self.self_account.clone(),
Expand All @@ -68,21 +75,18 @@ impl<'a, 'b: 'a, T: Trait> ExecutionContext<'a, 'b, T> {
depth: self.depth + 1,
};
vm::execute(&dest_code, &mut nested, gas_limit).map_err(|_| ())?
};

// TODO: Need to propagate gas_left.
// TODO: Need to return result buffer.

(exec_result, overlay.into_change_set())
} else {
// that was a plain transfer
(
} else {
// that was a plain transfer
vm::ExecutionResult {
gas_left: gas_limit,
return_data: Vec::new(),
},
ChangeSet::new(),
)
}
};

(exec_result, overlay.into_change_set())
};

self.account_db.commit(change_set);
Expand Down Expand Up @@ -132,6 +136,44 @@ impl<'a, 'b: 'a, T: Trait> ExecutionContext<'a, 'b, T> {
}
}

fn transfer<T: Trait>(
transactor: &T::AccountId,
dest: &T::AccountId,
value: T::Balance,
overlay: &mut OverlayAccountDb<T>,
) -> Result<(), &'static str> {

This comment was marked as resolved.

This comment was marked as resolved.

let would_create = overlay.get_balance(transactor).is_zero();
let fee = if would_create {
<staking::Module<T>>::creation_fee()
} else {
<staking::Module<T>>::transfer_fee()
};
let liability = value + fee;

let from_balance = overlay.get_balance(transactor);
if from_balance < liability {
return Err("balance too low to send value");
}
if would_create && value < <staking::Module<T>>::existential_deposit() {
return Err("value too low to create account");
}
if <staking::Module<T>>::bondage(transactor) > <system::Module<T>>::block_number() {
return Err("bondage too high to send value");
}

let to_balance = overlay.get_balance(dest);
if to_balance + value <= to_balance {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a possible confusion here: it looks like we define staking::Trait::Balance to be wrapping (non-panic), but we're using std traits Add/Sub etc, which by default is non-wrapping (panic). So if someone accidentally set staking::Trait::Balance to be, for example, usize. The code would panic.

Maybe it's worth considering to define another trait (like WrappingAdd?).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right! Will use checked_add here and in the staking module.

return Err("destination balance too high to receive value");
}

if transactor != dest {
overlay.set_balance(transactor, from_balance - liability);
overlay.set_balance(dest, to_balance + value);
}

Ok(())
}

impl<'a, 'b: 'a, T: Trait + 'b> vm::Ext for ExecutionContext<'a, 'b, T> {
type AccountId = T::AccountId;
type Balance = T::Balance;
Expand Down
23 changes: 14 additions & 9 deletions substrate/runtime/contract/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ pub use vm::Ext;

use exec::ExecutionContext;

use account_db::OverlayAccountDb;
use account_db::{AccountDb, DirectAccountDb, OverlayAccountDb};

use runtime_primitives::traits::RefInto;
use runtime_support::dispatch::Result;
Expand Down Expand Up @@ -147,18 +147,23 @@ impl<T: Trait> Module<T> {

let mut overlay = OverlayAccountDb::<T>::new(&account_db::DirectAccountDb);

let mut ctx = ExecutionContext {
// TODO: fuck
_caller: aux.clone(),
self_account: aux.clone(),
gas_price,
depth: 0,
account_db: &mut overlay,
let result = {
let mut ctx = ExecutionContext {
// TODO: fuck
_caller: aux.clone(),
self_account: aux.clone(),
gas_price,
depth: 0,
account_db: &mut overlay,
};
ctx.call(dest, value, gas_limit, data).map_err(|_| "execution failed")
};
let result = ctx.call(dest, value, gas_limit, data).map_err(|_| "execution failed");

// TODO: Can we return early or we always need to do some finalization steps?
result?;

account_db::DirectAccountDb.commit(overlay.into_change_set());

// TODO: commit changes from `overlay` to DirectAccountDb.
// TODO: finalization: refund `gas_left`.

Expand Down
32 changes: 32 additions & 0 deletions substrate/runtime/staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,38 @@ impl<T: Trait> Module<T> {
}
}

/// TODO: Document
pub fn commit_free_balance(who: &T::AccountId, balance: T::Balance) -> bool {
let ed = <Module<T>>::existential_deposit();
// If the balance is too low, then the account is reaped.
// NOTE: There are two balances for every account: `reserved_balance` and
// `free_balance`. This contract subsystem only cares about the latter: whenever
// the term "balance" is used *here* it should be assumed to mean "free balance"
// in the rest of the module.
// Free balance can never be less than ED. If that happens, it gets reduced to zero
// and the account information relevant to this subsystem is deleted (i.e. the
// account is reaped).
// NOTE: This is orthogonal to the `Bondage` value that an account has, a high
// value of which makes even the `free_balance` unspendable.
// TODO: enforce this for the other balance-altering functions.
if balance < ed {
Self::on_free_too_low(who);
false
} else {
if !<FreeBalance<T>>::exists(who) {
let outcome = Self::new_account(&who, balance);
let credit = match outcome {
NewAccountOutcome::GoodHint => balance + <Module<T>>::reclaim_rebate(),
_ => balance,
};
<FreeBalance<T>>::insert(who, credit);
} else {
<FreeBalance<T>>::insert(who, balance);
}
true
}
}

/// Deducts up to `value` from the combined balance of `who`, preferring to deduct from the
/// free balance. This function cannot fail.
///
Expand Down