Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Caller is origin implementation #1991

Open
wants to merge 49 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
e7f1b8f
Implementing stuff needed for instantiate_contract().
Oct 27, 2023
506e95d
Implemented return_value() on integration tests.
Oct 27, 2023
bc8688b
A couple fixes for E2E environment.
Oct 27, 2023
6ccd54b
Forgot to delete some fluff.
Oct 27, 2023
34854c5
Fixed dead code warnings.
Oct 27, 2023
c75ed7d
Added tests.
Oct 27, 2023
3ccb01f
Fixed-up tomls.
Oct 27, 2023
2d1950a
Updated stderr test files.
Oct 27, 2023
2d13b21
Updated CHANGELOG.
Oct 27, 2023
817f3cc
Passed through rustfmt.
Oct 27, 2023
6c4efc6
Passed through clippy.
Oct 27, 2023
25e1810
Passed through rustfmt again.
Helios-vmg Oct 30, 2023
3042f4d
Fixed failing contract builds.
Helios-vmg Oct 31, 2023
8f78fdd
Revert "Updated stderr test files."
Helios-vmg Oct 31, 2023
b350252
Fixed format errors.
Helios-vmg Oct 31, 2023
2dfb9ed
Fixed failing test.
Oct 31, 2023
a715026
Updated stderr test values.
Oct 31, 2023
9c74b08
Fixed some dependencies for doc tests.
Helios-vmg Oct 31, 2023
ea15b62
Fixed rustfmt issues.
Oct 31, 2023
4e8fdc9
Implemented code_hash() and set_code_hash().
Nov 7, 2023
9981c7f
Minor behavior correction for instantiate_contract().
Nov 7, 2023
12297f8
Merge branch 'code_hash-implementation' into invoke_contract-implemen…
Nov 7, 2023
b6478d9
Tentative invoke_contract() implementation.
Nov 7, 2023
4c04eba
Added invoke_contract_delegate() skeleton.
Nov 7, 2023
7d4f265
Obviated unsafe block.
Nov 7, 2023
94f3484
own_code_hash implementation
ramirez7358 Nov 8, 2023
4de3aa0
Add own-code-hash integration test
ramirez7358 Nov 8, 2023
439e90c
Remove unused use.
Nov 8, 2023
1c33d83
Merge branch 'code_hash-implementation' into invoke_contract-implemen…
Nov 8, 2023
057e98c
Added some missing semantics.
Nov 8, 2023
b684b74
Passed through rustfmt.
Nov 9, 2023
cd6e687
Passed through clippy.
Nov 9, 2023
c9c7d85
Fixed own_code_hash test.
Nov 9, 2023
7a8f98d
Tightening up code.
Nov 9, 2023
37a00d9
Improved contract invokation tests. Fixed some things.
Nov 9, 2023
1fe7be9
caller-is-origin implementation
ramirez7358 Nov 10, 2023
648c65c
Fix integration tests
ramirez7358 Nov 10, 2023
3c1d66f
Added tests.
Nov 10, 2023
6cc180c
Removed unused type parameter.
Nov 10, 2023
cc80e57
Fix e2e tests
ramirez7358 Nov 13, 2023
c135409
Clippy and fmt
ramirez7358 Nov 13, 2023
4e87e30
Updated changelog.
Helios-vmg Nov 13, 2023
f87e5dd
Add comment and fix integration tests
ramirez7358 Nov 13, 2023
58bf736
Merge branch 'integration-tests-api-implementation' into 'caller_is_o…
ramirez7358 Nov 14, 2023
e5c4eda
Add changelog
ramirez7358 Nov 14, 2023
68de165
Merge branch 'master' into caller_is_origin-implementation
ramirez7358 Nov 14, 2023
3e32419
Fixed clippy errors.
Nov 15, 2023
369ec49
Merge branch 'integration-tests-api-implementations' into 'caller_is_…
ramirez7358 Nov 16, 2023
784e2b8
Passed through rustfmt.
ramirez7358 Nov 16, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [E2E] Call builders and extra gas margin option - [#1917](https://github.com/paritytech/ink/pull/1917)
- Make `set_code_hash` generic - [#1906](https://github.com/paritytech/ink/pull/1906)
- Clean E2E configuration parsing - [#1922](https://github.com/paritytech/ink/pull/1922)
- Implement contract invokation in off-chain environment engine - [#1957](https://github.com/paritytech/ink/pull/1988)
- Implement `caller_is_origin()` in off-chain environment engine - [#1991](https://github.com/paritytech/ink/pull/1991)

### Changed
- Fail when decoding from storage and not all bytes consumed - [#1897](https://github.com/paritytech/ink/pull/1897)
Expand Down
58 changes: 58 additions & 0 deletions crates/engine/src/database.rs
Expand Up @@ -18,6 +18,9 @@ use std::collections::HashMap;

const BALANCE_OF: &[u8] = b"balance:";
const STORAGE_OF: &[u8] = b"contract-storage:";
const CONTRACT_PREFIX: &[u8] = b"contract:";
const MSG_HANDLER_OF: &[u8] = b"message-handler:";
const CODE_HASH_OF: &[u8] = b"code-hash:";

/// Returns the database key under which to find the balance for account `who`.
pub fn balance_of_key(who: &[u8]) -> [u8; 32] {
Expand All @@ -35,20 +38,47 @@ pub fn storage_of_contract_key(who: &[u8], key: &[u8]) -> [u8; 32] {
hashed_key
}

pub type MessageHandler = fn(Vec<u8>) -> Vec<u8>;

pub fn contract_key(f: MessageHandler) -> [u8; 32] {
let f = f as usize;
let f = f.to_le_bytes();
let keyed = f.to_vec().to_keyed_vec(CONTRACT_PREFIX);
let mut ret: [u8; 32] = [0; 32];
super::hashing::blake2b_256(&keyed[..], &mut ret);
ret
}

pub fn message_handler_of_contract_key(key: &[u8]) -> [u8; 32] {
let keyed = key.to_vec().to_keyed_vec(MSG_HANDLER_OF);
let mut hashed_key: [u8; 32] = [0; 32];
super::hashing::blake2b_256(&keyed[..], &mut hashed_key);
hashed_key
}

pub fn code_hash_of_key(key: &Vec<u8>) -> [u8; 32] {
let keyed = key.to_keyed_vec(CODE_HASH_OF);
let mut hashed_key: [u8; 32] = [0; 32];
super::hashing::blake2b_256(&keyed[..], &mut hashed_key);
hashed_key
}

/// The chain database.
///
/// Everything is stored in here: accounts, balances, contract storage, etc..
/// Just like in Substrate a prefix hash is computed for every contract.
#[derive(Default)]
pub struct Database {
hmap: HashMap<Vec<u8>, Vec<u8>>,
fmap: HashMap<Vec<u8>, MessageHandler>,
}

impl Database {
/// Creates a new database instance.
pub fn new() -> Self {
Database {
hmap: HashMap::new(),
fmap: HashMap::new(),
}
}

Expand Down Expand Up @@ -128,6 +158,34 @@ impl Database {
.and_modify(|v| *v = encoded_balance.clone())
.or_insert(encoded_balance);
}

pub fn set_contract_message_handler(&mut self, handler: MessageHandler) -> [u8; 32] {
let key = contract_key(handler);
let hashed_key = message_handler_of_contract_key(&key);
self.fmap
.entry(hashed_key.to_vec())
.and_modify(|x| *x = handler)
.or_insert(handler);
key
}

pub fn get_contract_message_handler(&mut self, key: &[u8]) -> MessageHandler {
let hashed_key = message_handler_of_contract_key(key);
*self.fmap.get(&hashed_key.to_vec()).unwrap()
}

pub fn set_code_hash(&mut self, account: &Vec<u8>, code_hash: &[u8]) {
let hashed_key = code_hash_of_key(account);
self.hmap
.entry(hashed_key.to_vec())
.and_modify(|x| *x = code_hash.to_vec())
.or_insert(code_hash.to_vec());
}

pub fn get_code_hash(&self, account: &Vec<u8>) -> Option<Vec<u8>> {
let hashed_key = code_hash_of_key(account);
self.get(&hashed_key).cloned()
}
}

#[cfg(test)]
Expand Down
2 changes: 2 additions & 0 deletions crates/engine/src/exec_context.rs
Expand Up @@ -45,6 +45,8 @@ pub struct ExecContext {
pub block_timestamp: BlockTimestamp,
/// Known contract accounts
pub contracts: Vec<Vec<u8>>,
/// This value is used to know the origin of the contract calls.
pub depth: u8,
}

impl ExecContext {
Expand Down
4 changes: 4 additions & 0 deletions crates/engine/src/ext.rs
Expand Up @@ -505,6 +505,10 @@ impl Engine {
Err(_) => Err(Error::EcdsaRecoveryFailed),
}
}

pub fn caller_is_origin(&self) -> bool {
self.exec_context.depth == 0
}
}

/// Copies the `slice` into `output`.
Expand Down
2 changes: 1 addition & 1 deletion crates/engine/src/lib.rs
Expand Up @@ -23,7 +23,7 @@ pub mod test_api;
mod chain_extension;
mod database;
mod exec_context;
mod hashing;
pub mod hashing;
mod types;

#[cfg(test)]
Expand Down
2 changes: 2 additions & 0 deletions crates/env/Cargo.toml
Expand Up @@ -60,6 +60,7 @@ ink = { path = "../ink" }
[features]
default = ["std"]
std = [
"ink/std",
"ink_allocator/std",
"ink_prelude/std",
"ink_primitives/std",
Expand All @@ -77,6 +78,7 @@ std = [
"sha3",
"blake2",
]
test_instantiate = []

# Enable contract debug messages via `debug_print!` and `debug_println!`.
ink-debug = []
Expand Down
27 changes: 24 additions & 3 deletions crates/env/src/api.rs
Expand Up @@ -37,8 +37,10 @@ use crate::{
CryptoHash,
HashOutput,
},
types::Gas,
Environment,
types::{
Environment,
Gas,
},
Result,
};
use ink_storage_traits::Storable;
Expand Down Expand Up @@ -336,7 +338,9 @@ pub fn instantiate_contract<E, ContractRef, Args, Salt, R>(
>
where
E: Environment,
ContractRef: FromAccountId<E>,
ContractRef: FromAccountId<E> + crate::ContractReverseReference,
<ContractRef as crate::ContractReverseReference>::Type:
crate::reflect::ContractConstructorDecoder,
Args: scale::Encode,
Salt: AsRef<[u8]>,
R: ConstructorReturnType<ContractRef>,
Expand Down Expand Up @@ -426,6 +430,7 @@ where
/// # Note
///
/// This function stops the execution of the contract immediately.
#[cfg(not(feature = "test_instantiate"))]
pub fn return_value<R>(return_flags: ReturnFlags, return_value: &R) -> !
where
R: scale::Encode,
Expand All @@ -435,6 +440,22 @@ where
})
}

/// Returns the value back to the caller of the executed contract.
///
/// # Note
///
/// When the test_instantiate feature is used, the contract is allowed to
/// return normally. This feature should only be used for integration tests.
#[cfg(feature = "test_instantiate")]
pub fn return_value<R>(return_flags: ReturnFlags, return_value: &R)
where
R: scale::Encode,
{
<EnvInstance as OnInstance>::on_instance(|instance| {
EnvBackend::return_value::<R>(instance, return_flags, return_value)
})
}

/// Appends the given message to the debug message buffer.
pub fn debug_message(message: &str) {
<EnvInstance as OnInstance>::on_instance(|instance| {
Expand Down
21 changes: 19 additions & 2 deletions crates/env/src/backend.rs
Expand Up @@ -26,7 +26,7 @@ use crate::{
CryptoHash,
HashOutput,
},
Environment,
types::Environment,
Result,
};
use ink_storage_traits::Storable;
Expand Down Expand Up @@ -247,10 +247,25 @@ pub trait EnvBackend {
///
/// The `flags` parameter can be used to revert the state changes of the
/// entire execution if necessary.
#[cfg(not(feature = "test_instantiate"))]
fn return_value<R>(&mut self, flags: ReturnFlags, return_value: &R) -> !
where
R: scale::Encode;

/// Returns the value back to the caller of the executed contract.
///
/// # Note
///
/// When the test_instantiate feature is used, the contract is allowed to
/// return normally. This feature should only be used for integration tests.
///
/// The `flags` parameter can be used to revert the state changes of the
/// entire execution if necessary.
#[cfg(feature = "test_instantiate")]
fn return_value<R>(&mut self, flags: ReturnFlags, return_value: &R)
where
R: scale::Encode;

/// Emit a custom debug message.
///
/// The message is appended to the debug buffer which is then supplied to the calling
Expand Down Expand Up @@ -469,7 +484,9 @@ pub trait TypedEnvBackend: EnvBackend {
>
where
E: Environment,
ContractRef: FromAccountId<E>,
ContractRef: FromAccountId<E> + crate::ContractReverseReference,
<ContractRef as crate::ContractReverseReference>::Type:
crate::reflect::ContractConstructorDecoder,
Args: scale::Encode,
Salt: AsRef<[u8]>,
R: ConstructorReturnType<ContractRef>;
Expand Down
6 changes: 4 additions & 2 deletions crates/env/src/call/call_builder.rs
Expand Up @@ -23,8 +23,10 @@ use crate::{
},
ExecutionInput,
},
types::Gas,
Environment,
types::{
Environment,
Gas,
},
Error,
};
use core::marker::PhantomData;
Expand Down
14 changes: 11 additions & 3 deletions crates/env/src/call/create_builder.rs
Expand Up @@ -24,8 +24,8 @@ use crate::{
ExecutionInput,
Selector,
},
types::Environment,
ContractEnv,
Environment,
Error,
};
use core::marker::PhantomData;
Expand Down Expand Up @@ -240,7 +240,11 @@ where
impl<E, ContractRef, Args, Salt, R> CreateParams<E, ContractRef, Args, Salt, R>
where
E: Environment,
ContractRef: FromAccountId<E>,
ContractRef: FromAccountId<E> + crate::ContractReverseReference,
<ContractRef as crate::ContractReverseReference>::Type:
crate::reflect::ContractConstructorDecoder,
<ContractRef as crate::ContractReverseReference>::Type:
crate::reflect::ContractMessageDecoder,
Args: scale::Encode,
Salt: AsRef<[u8]>,
R: ConstructorReturnType<ContractRef>,
Expand Down Expand Up @@ -721,7 +725,11 @@ impl<E, ContractRef, GasLimit, Args, Salt, RetType>
>
where
E: Environment,
ContractRef: FromAccountId<E>,
ContractRef: FromAccountId<E> + crate::ContractReverseReference,
<ContractRef as crate::ContractReverseReference>::Type:
crate::reflect::ContractConstructorDecoder,
<ContractRef as crate::ContractReverseReference>::Type:
crate::reflect::ContractMessageDecoder,
GasLimit: Unwrap<Output = u64>,
Args: scale::Encode,
Salt: AsRef<[u8]>,
Expand Down
4 changes: 2 additions & 2 deletions crates/env/src/engine/mod.rs
Expand Up @@ -77,7 +77,7 @@ pub(crate) fn decode_instantiate_result<I, E, ContractRef, R>(
) -> EnvResult<ConstructorResult<<R as ConstructorReturnType<ContractRef>>::Output>>
where
I: scale::Input,
E: crate::Environment,
E: crate::types::Environment,
ContractRef: FromAccountId<E>,
R: ConstructorReturnType<ContractRef>,
{
Expand All @@ -102,7 +102,7 @@ fn decode_instantiate_err<I, E, ContractRef, R>(
) -> EnvResult<ConstructorResult<<R as ConstructorReturnType<ContractRef>>::Output>>
where
I: scale::Input,
E: crate::Environment,
E: crate::types::Environment,
ContractRef: FromAccountId<E>,
R: ConstructorReturnType<ContractRef>,
{
Expand Down