From 4ded4181a651fe9c26850f908e4ab63bf952cab6 Mon Sep 17 00:00:00 2001 From: Anton Gavrilov Date: Mon, 3 Dec 2018 20:44:36 +0100 Subject: [PATCH] Version and notification for private contract wrapper added (#9761) * Version and notification for private contract wrapper added * Error handling improved * Style for comments in file fixed * TODO issue added into comments --- ethcore/private-tx/res/private.evm | 2 +- ethcore/private-tx/res/private.json | 172 +++++++++++++++++++++++++++- ethcore/private-tx/src/lib.rs | 159 ++++++++++++++----------- 3 files changed, 267 insertions(+), 66 deletions(-) diff --git a/ethcore/private-tx/res/private.evm b/ethcore/private-tx/res/private.evm index cd19d757a..e1da9bb60 100644 --- a/ethcore/private-tx/res/private.evm +++ b/ethcore/private-tx/res/private.evm @@ -1 +1 @@ -6060604052341561000f57600080fd5b604051610b0d380380610b0d833981016040528080518201919060200180518201919060200180518201919050508260009080519060200190610053929190610092565b50816002908051906020019061006a92919061011c565b50806001908051906020019061008192919061011c565b506001600381905550505050610204565b82805482825590600052602060002090810192821561010b579160200282015b8281111561010a5782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550916020019190600101906100b2565b5b509050610118919061019c565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061015d57805160ff191683800117855561018b565b8280016001018555821561018b579182015b8281111561018a57825182559160200191906001019061016f565b5b50905061019891906101df565b5090565b6101dc91905b808211156101d857600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055506001016101a2565b5090565b90565b61020191905b808211156101fd5760008160009055506001016101e5565b5090565b90565b6108fa806102136000396000f300606060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806317ac53a21461007d57806324c12bf61461019a57806335aa2e4414610228578063affed0e01461028b578063b7ab4db5146102b4578063c19d93fb1461031e575b600080fd5b341561008857600080fd5b610198600480803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919050506103ac565b005b34156101a557600080fd5b6101ad610600565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101ed5780820151818401526020810190506101d2565b50505050905090810190601f16801561021a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561023357600080fd5b610249600480803590602001909190505061069e565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561029657600080fd5b61029e6106dd565b6040518082815260200191505060405180910390f35b34156102bf57600080fd5b6102c76106e3565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561030a5780820151818401526020810190506102ef565b505050509050019250505060405180910390f35b341561032957600080fd5b610331610777565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610371578082015181840152602081019050610356565b50505050905090810190601f16801561039e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6000806040805190810160405280876040518082805190602001908083835b6020831015156103f057805182526020820191506020810190506020830392506103cb565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191660001916815260200160035460010260001916600019168152506040518082600260200280838360005b8381101561046657808201518184015260208101905061044b565b5050505090500191505060405180910390209150600090505b6000805490508110156105d55760008181548110151561049b57fe5b906000526020600020900160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660018387848151811015156104ee57fe5b90602001906020020151878581518110151561050657fe5b90602001906020020151878681518110151561051e57fe5b90602001906020020151604051600081526020016040526000604051602001526040518085600019166000191681526020018460ff1660ff16815260200183600019166000191681526020018260001916600019168152602001945050505050602060405160208103908084039060008661646e5a03f115156105a057600080fd5b50506020604051035173ffffffffffffffffffffffffffffffffffffffff161415156105c857fe5b808060010191505061047f565b85600190805190602001906105eb929190610815565b50600160035401600381905550505050505050565b60028054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156106965780601f1061066b57610100808354040283529160200191610696565b820191906000526020600020905b81548152906001019060200180831161067957829003601f168201915b505050505081565b6000818154811015156106ad57fe5b90600052602060002090016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60035481565b6106eb610895565b600080548060200260200160405190810160405280929190818152602001828054801561076d57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610723575b5050505050905090565b60018054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561080d5780601f106107e25761010080835404028352916020019161080d565b820191906000526020600020905b8154815290600101906020018083116107f057829003601f168201915b505050505081565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061085657805160ff1916838001178555610884565b82800160010185558215610884579182015b82811115610883578251825591602001919060010190610868565b5b50905061089191906108a9565b5090565b602060405190810160405280600081525090565b6108cb91905b808211156108c75760008160009055506001016108af565b5090565b905600a165627a7a723058200ae0215fae320b646a22fdd58278b328f46d915bd65ddbfeb5b4a09643d6e0220029 +60806040523480156200001157600080fd5b5060405162000d5238038062000d52833981018060405281019080805182019291906020018051820192919060200180518201929190505050826000908051906020019062000062929190620000a6565b5081600290805190602001906200007b92919062000135565b5080600190805190602001906200009492919062000135565b5060016003819055505050506200022a565b82805482825590600052602060002090810192821562000122579160200282015b82811115620001215782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555091602001919060010190620000c7565b5b509050620001319190620001bc565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200017857805160ff1916838001178555620001a9565b82800160010185558215620001a9579182015b82811115620001a85782518255916020019190600101906200018b565b5b509050620001b8919062000202565b5090565b620001ff91905b80821115620001fb57600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550600101620001c3565b5090565b90565b6200022791905b808211156200022357600081600090555060010162000209565b5090565b90565b610b18806200023a6000396000f30060806040526004361061008e576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630d8e6e2c1461009357806317ac53a2146100c457806324c12bf6146101f657806335aa2e44146102865780639326c281146102f3578063affed0e01461037c578063b7ab4db5146103a7578063c19d93fb14610413575b600080fd5b34801561009f57600080fd5b506100a86104a3565b604051808260ff1660ff16815260200191505060405180910390f35b3480156100d057600080fd5b506101f4600480360381019080803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919291929080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509192919290803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091929192905050506104ac565b005b34801561020257600080fd5b5061020b610765565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561024b578082015181840152602081019050610230565b50505050905090810190601f1680156102785780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561029257600080fd5b506102b160048036038101908080359060200190929190505050610803565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156102ff57600080fd5b5061037a600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050610841565b005b34801561038857600080fd5b50610391610915565b6040518082815260200191505060405180910390f35b3480156103b357600080fd5b506103bc61091b565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156103ff5780820151818401526020810190506103e4565b505050509050019250505060405180910390f35b34801561041f57600080fd5b506104286109a9565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561046857808201518184015260208101905061044d565b50505050905090810190601f1680156104955780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60006002905090565b6000806040805190810160405280876040518082805190602001908083835b6020831015156104f057805182526020820191506020810190506020830392506104cb565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191660001916815260200160035460010260001916600019168152506040516020018082600260200280838360005b8381101561056957808201518184015260208101905061054e565b505050509050019150506040516020818303038152906040526040518082805190602001908083835b6020831015156105b75780518252602082019150602081019050602083039250610592565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209150600090505b60008054905081101561073a5760008181548110151561060757fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600183878481518110151561065957fe5b90602001906020020151878581518110151561067157fe5b90602001906020020151878681518110151561068957fe5b90602001906020020151604051600081526020016040526040518085600019166000191681526020018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200194505050505060206040516020810390808403906000865af1158015610704573d6000803e3d6000fd5b5050506020604051035173ffffffffffffffffffffffffffffffffffffffff1614151561072d57fe5b80806001019150506105eb565b8560019080519060200190610750929190610a47565b50600160035401600381905550505050505050565b60028054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156107fb5780601f106107d0576101008083540402835291602001916107fb565b820191906000526020600020905b8154815290600101906020018083116107de57829003601f168201915b505050505081565b60008181548110151561081257fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7fd75b949e4bbba98bcf6d2878e9175f5608dde180a67ba25d0f2020067e17fdac8282604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019080838360005b838110156108d65780820151818401526020810190506108bb565b50505050905090810190601f1680156109035780820380516001836020036101000a031916815260200191505b50935050505060405180910390a15050565b60035481565b6060600080548060200260200160405190810160405280929190818152602001828054801561099f57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610955575b5050505050905090565b60018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610a3f5780601f10610a1457610100808354040283529160200191610a3f565b820191906000526020600020905b815481529060010190602001808311610a2257829003601f168201915b505050505081565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610a8857805160ff1916838001178555610ab6565b82800160010185558215610ab6579182015b82811115610ab5578251825591602001919060010190610a9a565b5b509050610ac39190610ac7565b5090565b610ae991905b80821115610ae5576000816000905550600101610acd565b5090565b905600a165627a7a723058205bbab96bfbda16ccdb4900d9280aa9d511c3d3687be1ca598dd784987f55ebb70029 diff --git a/ethcore/private-tx/res/private.json b/ethcore/private-tx/res/private.json index 82a5e86bc..0d8f17543 100644 --- a/ethcore/private-tx/res/private.json +++ b/ethcore/private-tx/res/private.json @@ -1 +1,171 @@ -[{"constant": false,"inputs": [{"name": "newState","type": "bytes"},{"name": "v","type": "uint8[]"},{"name": "r","type": "bytes32[]"},{"name": "s","type": "bytes32[]"}],"name": "setState","outputs": [],"payable": false,"stateMutability": "nonpayable","type": "function"},{"constant": true,"inputs": [],"name": "code","outputs": [{"name": "","type": "bytes"}],"payable": false,"stateMutability": "view","type": "function"},{"constant": true,"inputs": [{"name": "","type": "uint256"}],"name": "validators","outputs": [{"name": "","type": "address"}],"payable": false,"stateMutability": "view","type": "function"},{"constant": true,"inputs": [],"name": "nonce","outputs": [{"name": "","type": "uint256"}],"payable": false,"stateMutability": "view","type": "function"},{"constant": true,"inputs": [],"name": "getValidators","outputs": [{"name": "","type": "address[]"}],"payable": false,"stateMutability": "view","type": "function"},{"constant": true,"inputs": [],"name": "state","outputs": [{"name": "","type": "bytes"}],"payable": false,"stateMutability": "view","type": "function"},{"inputs": [{"name": "initialValidators","type": "address[]"},{"name": "initialCode","type": "bytes"},{"name": "initialState","type": "bytes"}],"payable": false,"stateMutability": "nonpayable","type": "constructor"}] +[ + { + "constant": true, + "inputs": [], + "name": "getVersion", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "newState", + "type": "bytes" + }, + { + "name": "v", + "type": "uint8[]" + }, + { + "name": "r", + "type": "bytes32[]" + }, + { + "name": "s", + "type": "bytes32[]" + } + ], + "name": "setState", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "code", + "outputs": [ + { + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "", + "type": "uint256" + } + ], + "name": "validators", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "changesOriginator", + "type": "address" + }, + { + "name": "originalTransactionHash", + "type": "bytes" + } + ], + "name": "notifyChanges", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "nonce", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getValidators", + "outputs": [ + { + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "state", + "outputs": [ + { + "name": "", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "name": "initialValidators", + "type": "address[]" + }, + { + "name": "initialCode", + "type": "bytes" + }, + { + "name": "initialState", + "type": "bytes" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "changesOriginator", + "type": "address" + }, + { + "indexed": false, + "name": "originalTransactionHash", + "type": "bytes" + } + ], + "name": "PrivateStateChanged", + "type": "event" + } +] \ No newline at end of file diff --git a/ethcore/private-tx/src/lib.rs b/ethcore/private-tx/src/lib.rs index 12d063974..5e480b7ed 100644 --- a/ethcore/private-tx/src/lib.rs +++ b/ethcore/private-tx/src/lib.rs @@ -103,6 +103,12 @@ const INIT_VEC_LEN: usize = 16; /// Size of nonce cache const NONCE_CACHE_SIZE: usize = 128; +/// Version for the initial private contract wrapper +const INITIAL_PRIVATE_CONTRACT_VER: usize = 1; + +/// Version for the private contract notification about private state changes added +const PRIVATE_CONTRACT_WITH_NOTIFICATION_VER: usize = 2; + /// Configurtion for private transaction provider #[derive(Default, PartialEq, Debug, Clone)] pub struct ProviderConfig { @@ -199,36 +205,30 @@ impl Provider where { bail!(ErrorKind::SignerAccountNotSet); } let tx_hash = signed_transaction.hash(); - match signed_transaction.action { - Action::Create => { - bail!(ErrorKind::BadTransactonType); - } - Action::Call(contract) => { - let data = signed_transaction.rlp_bytes(); - let encrypted_transaction = self.encrypt(&contract, &Self::iv_from_transaction(&signed_transaction), &data)?; - let private = PrivateTransaction::new(encrypted_transaction, contract); - // TODO [ToDr] Using BlockId::Latest is bad here, - // the block may change in the middle of execution - // causing really weird stuff to happen. - // We should retrieve hash and stick to that. IMHO - // best would be to change the API and only allow H256 instead of BlockID - // in private-tx to avoid such mistakes. - let contract_nonce = self.get_contract_nonce(&contract, BlockId::Latest)?; - let private_state = self.execute_private_transaction(BlockId::Latest, &signed_transaction)?; - trace!(target: "privatetx", "Private transaction created, encrypted transaction: {:?}, private state: {:?}", private, private_state); - let contract_validators = self.get_validators(BlockId::Latest, &contract)?; - trace!(target: "privatetx", "Required validators: {:?}", contract_validators); - let private_state_hash = self.calculate_state_hash(&private_state, contract_nonce); - trace!(target: "privatetx", "Hashed effective private state for sender: {:?}", private_state_hash); - self.transactions_for_signing.write().add_transaction(private.hash(), signed_transaction, contract_validators, private_state, contract_nonce)?; - self.broadcast_private_transaction(private.hash(), private.rlp_bytes()); - Ok(Receipt { - hash: tx_hash, - contract_address: Some(contract), - status_code: 0, - }) - } - } + let contract = Self::contract_address_from_transaction(&signed_transaction).map_err(|_| ErrorKind::BadTransactonType)?; + let data = signed_transaction.rlp_bytes(); + let encrypted_transaction = self.encrypt(&contract, &Self::iv_from_transaction(&signed_transaction), &data)?; + let private = PrivateTransaction::new(encrypted_transaction, contract); + // TODO #9825 [ToDr] Using BlockId::Latest is bad here, + // the block may change in the middle of execution + // causing really weird stuff to happen. + // We should retrieve hash and stick to that. IMHO + // best would be to change the API and only allow H256 instead of BlockID + // in private-tx to avoid such mistakes. + let contract_nonce = self.get_contract_nonce(&contract, BlockId::Latest)?; + let private_state = self.execute_private_transaction(BlockId::Latest, &signed_transaction)?; + trace!(target: "privatetx", "Private transaction created, encrypted transaction: {:?}, private state: {:?}", private, private_state); + let contract_validators = self.get_validators(BlockId::Latest, &contract)?; + trace!(target: "privatetx", "Required validators: {:?}", contract_validators); + let private_state_hash = self.calculate_state_hash(&private_state, contract_nonce); + trace!(target: "privatetx", "Hashed effective private state for sender: {:?}", private_state_hash); + self.transactions_for_signing.write().add_transaction(private.hash(), signed_transaction, contract_validators, private_state, contract_nonce)?; + self.broadcast_private_transaction(private.hash(), private.rlp_bytes()); + Ok(Receipt { + hash: tx_hash, + contract_address: Some(contract), + status_code: 0, + }) } /// Calculate hash from united private state and contract nonce @@ -269,33 +269,30 @@ impl Provider where { self.broadcast_private_transaction(private_hash, transaction.private_transaction.rlp_bytes()); return Ok(()); } - let tx_action = transaction.transaction.action.clone(); - if let Action::Call(contract) = tx_action { - // TODO [ToDr] Usage of BlockId::Latest - let contract_nonce = self.get_contract_nonce(&contract, BlockId::Latest); - if let Err(e) = contract_nonce { - bail!("Cannot retrieve contract nonce: {:?}", e); - } - let contract_nonce = contract_nonce.expect("Error was checked before"); - let private_state = self.execute_private_transaction(BlockId::Latest, &transaction.transaction); - if let Err(e) = private_state { - bail!("Cannot retrieve private state: {:?}", e); - } - let private_state = private_state.expect("Error was checked before"); - let private_state_hash = self.calculate_state_hash(&private_state, contract_nonce); - trace!(target: "privatetx", "Hashed effective private state for validator: {:?}", private_state_hash); - let password = find_account_password(&self.passwords, &*self.accounts, &validator_account); - let signed_state = self.accounts.sign(validator_account, password, private_state_hash); - if let Err(e) = signed_state { - bail!("Cannot sign the state: {:?}", e); - } - let signed_state = signed_state.expect("Error was checked before"); - let signed_private_transaction = SignedPrivateTransaction::new(private_hash, signed_state, None); - trace!(target: "privatetx", "Sending signature for private transaction: {:?}", signed_private_transaction); - self.broadcast_signed_private_transaction(signed_private_transaction.hash(), signed_private_transaction.rlp_bytes()); - } else { - bail!("Incorrect type of action for the transaction"); + let contract = Self::contract_address_from_transaction(&transaction.transaction) + .map_err(|_| "Incorrect type of action for the transaction")?; + // TODO #9825 [ToDr] Usage of BlockId::Latest + let contract_nonce = self.get_contract_nonce(&contract, BlockId::Latest); + if let Err(e) = contract_nonce { + bail!("Cannot retrieve contract nonce: {:?}", e); } + let contract_nonce = contract_nonce.expect("Error was checked before"); + let private_state = self.execute_private_transaction(BlockId::Latest, &transaction.transaction); + if let Err(e) = private_state { + bail!("Cannot retrieve private state: {:?}", e); + } + let private_state = private_state.expect("Error was checked before"); + let private_state_hash = self.calculate_state_hash(&private_state, contract_nonce); + trace!(target: "privatetx", "Hashed effective private state for validator: {:?}", private_state_hash); + let password = find_account_password(&self.passwords, &*self.accounts, &validator_account); + let signed_state = self.accounts.sign(validator_account, password, private_state_hash); + if let Err(e) = signed_state { + bail!("Cannot sign the state: {:?}", e); + } + let signed_state = signed_state.expect("Error was checked before"); + let signed_private_transaction = SignedPrivateTransaction::new(private_hash, signed_state, None); + trace!(target: "privatetx", "Sending signature for private transaction: {:?}", signed_private_transaction); + self.broadcast_signed_private_transaction(signed_private_transaction.hash(), signed_private_transaction.rlp_bytes()); } } Ok(()) @@ -328,7 +325,7 @@ impl Provider where { let mut signatures = desc.received_signatures.clone(); signatures.push(signed_tx.signature()); let rsv: Vec = signatures.into_iter().map(|sign| sign.into_electrum().into()).collect(); - //Create public transaction + // Create public transaction let public_tx = self.public_transaction( desc.state.clone(), &desc.original_transaction, @@ -337,7 +334,7 @@ impl Provider where { desc.original_transaction.gas_price )?; trace!(target: "privatetx", "Last required signature received, public transaction created: {:?}", public_tx); - //Sign and add it to the queue + // Sign and add it to the queue let chain_id = desc.original_transaction.chain_id(); let hash = public_tx.hash(chain_id); let signer_account = self.signer_account.ok_or_else(|| ErrorKind::SignerAccountNotSet)?; @@ -351,13 +348,22 @@ impl Provider where { bail!(err); } } - //Remove from store for signing + // Notify about state changes + let contract = Self::contract_address_from_transaction(&desc.original_transaction)?; + // TODO #9825 Usage of BlockId::Latest + if self.get_contract_version(BlockId::Latest, &contract) >= PRIVATE_CONTRACT_WITH_NOTIFICATION_VER { + match self.state_changes_notify(BlockId::Latest, &contract, &desc.original_transaction.sender(), desc.original_transaction.hash()) { + Ok(_) => trace!(target: "privatetx", "Notification about private state changes sent"), + Err(err) => warn!(target: "privatetx", "Failed to send private state changed notification, error: {:?}", err), + } + } + // Remove from store for signing if let Err(err) = self.transactions_for_signing.write().remove(&private_hash) { warn!(target: "privatetx", "Failed to remove transaction from signing store, error: {:?}", err); bail!(err); } } else { - //Add signature to the store + // Add signature to the store match self.transactions_for_signing.write().add_signature(&private_hash, signed_tx.signature()) { Ok(_) => trace!(target: "privatetx", "Signature stored for private transaction"), Err(err) => { @@ -369,6 +375,16 @@ impl Provider where { Ok(()) } + fn contract_address_from_transaction(transaction: &SignedTransaction) -> Result { + match transaction.action { + Action::Call(contract) => Ok(contract), + _ => { + warn!(target: "privatetx", "Incorrect type of action for the transaction"); + bail!(ErrorKind::BadTransactonType); + } + } + } + fn last_required_signature(&self, desc: &PrivateTransactionSigningDesc, sign: Signature) -> Result { if desc.received_signatures.contains(&sign) { return Ok(false); @@ -474,7 +490,7 @@ impl Provider where { env_info.gas_limit = transaction.gas; let mut state = self.client.state_at(block).ok_or(ErrorKind::StatePruned)?; - // TODO: in case of BlockId::Latest these need to operate on the same state + // TODO #9825 in case of BlockId::Latest these need to operate on the same state let contract_address = match transaction.action { Action::Call(ref contract_address) => { let contract_code = Arc::new(self.get_decrypted_code(contract_address, block)?); @@ -536,7 +552,7 @@ impl Provider where { /// Returns the key from the key server associated with the contract pub fn contract_key_id(&self, contract_address: &Address) -> Result { - //current solution uses contract address extended with 0 as id + // Current solution uses contract address extended with 0 as id let contract_address_extended: H256 = contract_address.into(); Ok(H256::from_slice(&contract_address_extended)) @@ -615,6 +631,21 @@ impl Provider where { let value = self.client.call_contract(block, *address, data)?; decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)).into()) } + + fn get_contract_version(&self, block: BlockId, address: &Address) -> usize { + let (data, decoder) = private_contract::functions::get_version::call(); + match self.client.call_contract(block, *address, data) + .and_then(|value| decoder.decode(&value).map_err(|e| e.to_string())) { + Ok(version) => version.low_u64() as usize, + Err(_) => INITIAL_PRIVATE_CONTRACT_VER, + } + } + + fn state_changes_notify(&self, block: BlockId, address: &Address, originator: &Address, transaction_hash: H256) -> Result<(), Error> { + let (data, _) = private_contract::functions::notify_changes::call(*originator, transaction_hash.0.to_vec()); + let _value = self.client.call_contract(block, *address, data)?; + Ok(()) + } } pub trait Importer { @@ -644,12 +675,12 @@ impl Importer for Arc { .iter() .find(|address| self.validator_accounts.contains(address)); - //extract the original transaction + // Extract the original transaction let encrypted_data = private_tx.encrypted(); let transaction_bytes = self.decrypt(&contract, &encrypted_data)?; let original_tx: UnverifiedTransaction = Rlp::new(&transaction_bytes).as_val()?; let nonce_cache = NonceCache::new(NONCE_CACHE_SIZE); - //add to the queue for further verification + // Add to the queue for further verification self.transactions_for_verification.add_transaction( original_tx, validation_account.map(|&account| account),