-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Call private contract methods from another private contract (read-only) #10086
Conversation
ethcore/sync/src/tests/private.rs
Outdated
@@ -24,7 +24,7 @@ use ethcore::CreateContractAddress; | |||
use transaction::{Transaction, Action}; | |||
use ethcore::executive::{contract_address}; | |||
use ethcore::test_helpers::{push_block_with_transactions}; | |||
use ethcore_private_tx::{Provider, ProviderConfig, NoopEncryptor, Importer, SignedPrivateTransaction}; | |||
use ethcore_private_tx::{Provider, ProviderConfig, NoopEncryptor, Importer, SignedPrivateTransaction, StoringKeyProvider }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: extra tab
// Patch other available private contracts' states as well | ||
if let Some(key_server_account) = self.keys_provider.key_server_account() { | ||
if let Some(available_contracts) = self.keys_provider.available_keys(block, &key_server_account) { | ||
for private_contract in available_contracts { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This may be a performance bottleneck. I don't think we need to fix it immediately, but what we can do is:
- Add a hook in
Externalities::call
that checks the contract address. - From there, only patch an account in the state if it's actually called.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you're right! TODO added into the code and the corresponding task #10133 created
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, couple minor grumbles.
contract_address); | ||
|
||
let keys_acl_contract = self.keys_acl_contract.write(); | ||
keys_acl_contract.and(contract_address); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like a no-op, do we actually want to update the keys_acl_contract
? Can we test this function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. Sorry about that. Fixed, test added
impl StoringKeyProvider { | ||
/// Store available keys | ||
pub fn set_available_keys(&self, keys: &Vec<Address>) { | ||
let mut current = self.available_keys.write(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not just *self.available_keys.write() = Some(keys.clone())
?
if let Ok(value) = self.client.call_contract(block, acl_contract_address, data) { | ||
self.keys_to_addresses(decoder.decode(&value).ok()) | ||
} else { | ||
None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we log something here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it's not an exceptional situation
|
||
fn keys_to_addresses(&self, keys: Option<Vec<H256>>) -> Option<Vec<Address>> { | ||
keys.map(|key_values| { | ||
let mut addresses: Vec<Address> = Vec::new(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
key_values.iter().map(key_to_address).collect()
?
ethcore/private-tx/src/lib.rs
Outdated
@@ -511,25 +524,35 @@ impl Provider where { | |||
let (new_address, _) = ethcore_contract_address(engine.create_address_scheme(env_info.number), &sender, &nonce, &transaction.data); | |||
Some(new_address) | |||
}); | |||
let contract_address = contract_address.expect("Private contract address should be non zero by this moment; qed"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be
doesn't sound like a proof, where exactly is it supposed to be initialised? Can we reach this line if private transactions are not part of the registry?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re-phrased with more explicit proof.
ethcore/private-tx/src/lib.rs
Outdated
}; | ||
Ok(PrivateExecutionResult { | ||
code: encrypted_code, | ||
state: encrypted_storage, | ||
contract_address, | ||
contract_address: Some(contract_address), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it's worth to change the type if it's always Some
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep
This reverts commit 476c132.
0d49ce6
to
74931d9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, minor grumble regarding redudant .expect
ethcore/private-tx/src/lib.rs
Outdated
@@ -512,25 +525,36 @@ impl Provider where { | |||
let (new_address, _) = ethcore_contract_address(engine.create_address_scheme(env_info.number), &sender, &nonce, &transaction.data); | |||
Some(new_address) | |||
}); | |||
let contract_address = contract_address.expect("Private contract address is non zero by this point, \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe change the above line to unwrap_or_else(||
?
The proof won't be necessary and also the contract address will be evaluated lazily.
* master: fix: parity-clib/examples/cpp/CMakeLists.txt (#10313) CI optimizations (#10297) Increase number of requested block bodies in chain sync (#10247) Deprecate account management (#10213) Properly handle check_epoch_end_signal errors (#10015) fix(osx and windows builds): bump parity-daemonize (#10291) Add missing step for Using `systemd` service file (#10175) Call private contract methods from another private contract (read-only) (#10086) update ring to 0.14 (#10262) fix(secret-store): deprecation warning (#10301) Update to jsonrpc-derive 10.0.2, fixes aliases bug (#10300) Convert to jsonrpc-derive, use jsonrpc-* from crates.io (#10298)
This PR adds possibility to make calls of private contract methods from another private contract (with condition, that caller has access to the keys for both private contracts).
In order to achieve this, ABI of permissioning contract of Secret Store was extended with availableKeys method, that returns all keys, available for the account.
The further solution is rather straightforward: after patching the state for the current private contract, we also patch states for all private contracts, available for the node, and execute the private transaction on this state.
Some details of the solution:
Closes #9199