Signer with Unlocked Account (#1398)
This commit is contained in:
parent
e346cbc7f9
commit
9a1e1b7c89
@ -205,6 +205,13 @@ impl AccountProvider {
|
|||||||
self.unlock_account(account, password, Unlock::Temp)
|
self.unlock_account(account, password, Unlock::Temp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if given account is unlocked
|
||||||
|
pub fn is_unlocked<A>(&self, account: A) -> bool where Address: From<A> {
|
||||||
|
let account = Address::from(account).into();
|
||||||
|
let unlocked = self.unlocked.read().unwrap();
|
||||||
|
unlocked.get(&account).is_some()
|
||||||
|
}
|
||||||
|
|
||||||
/// Signs the message. Account must be unlocked.
|
/// Signs the message. Account must be unlocked.
|
||||||
pub fn sign<A, M>(&self, account: A, message: M) -> Result<H520, Error> where Address: From<A>, Message: From<M> {
|
pub fn sign<A, M>(&self, account: A, message: M) -> Result<H520, Error> where Address: From<A>, Message: From<M> {
|
||||||
let account = Address::from(account).into();
|
let account = Address::from(account).into();
|
||||||
|
@ -198,6 +198,12 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Display warning about using unlock with signer
|
||||||
|
if conf.args.flag_signer && conf.args.flag_unlock.is_some() {
|
||||||
|
warn!("Using Trusted Signer and --unlock is not recommended!");
|
||||||
|
warn!("NOTE that Signer will not ask you to confirm transactions from unlocked account.");
|
||||||
|
}
|
||||||
|
|
||||||
// Secret Store
|
// Secret Store
|
||||||
let account_service = Arc::new(conf.account_service());
|
let account_service = Arc::new(conf.account_service());
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ pub fn setup_rpc<T: Extendable>(server: T, deps: Arc<Dependencies>, apis: ApiSet
|
|||||||
server.add_delegate(EthFilterClient::new(&deps.client, &deps.miner).to_delegate());
|
server.add_delegate(EthFilterClient::new(&deps.client, &deps.miner).to_delegate());
|
||||||
|
|
||||||
if deps.signer_port.is_some() {
|
if deps.signer_port.is_some() {
|
||||||
server.add_delegate(EthSigningQueueClient::new(&deps.signer_queue, &deps.client, &deps.miner).to_delegate());
|
server.add_delegate(EthSigningQueueClient::new(&deps.signer_queue, &deps.client, &deps.miner, &deps.secret_store).to_delegate());
|
||||||
} else {
|
} else {
|
||||||
server.add_delegate(EthSigningUnsafeClient::new(&deps.client, &deps.secret_store, &deps.miner).to_delegate());
|
server.add_delegate(EthSigningUnsafeClient::new(&deps.client, &deps.secret_store, &deps.miner).to_delegate());
|
||||||
}
|
}
|
||||||
|
@ -43,15 +43,17 @@ fn fill_optional_fields<C, M>(request: &mut TransactionRequest, client: &C, mine
|
|||||||
/// Implementation of functions that require signing when no trusted signer is used.
|
/// Implementation of functions that require signing when no trusted signer is used.
|
||||||
pub struct EthSigningQueueClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
pub struct EthSigningQueueClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
||||||
queue: Weak<ConfirmationsQueue>,
|
queue: Weak<ConfirmationsQueue>,
|
||||||
|
accounts: Weak<AccountProvider>,
|
||||||
client: Weak<C>,
|
client: Weak<C>,
|
||||||
miner: Weak<M>,
|
miner: Weak<M>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, M> EthSigningQueueClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
impl<C, M> EthSigningQueueClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
||||||
/// Creates a new signing queue client given shared signing queue.
|
/// Creates a new signing queue client given shared signing queue.
|
||||||
pub fn new(queue: &Arc<ConfirmationsQueue>, client: &Arc<C>, miner: &Arc<M>) -> Self {
|
pub fn new(queue: &Arc<ConfirmationsQueue>, client: &Arc<C>, miner: &Arc<M>, accounts: &Arc<AccountProvider>) -> Self {
|
||||||
EthSigningQueueClient {
|
EthSigningQueueClient {
|
||||||
queue: Arc::downgrade(queue),
|
queue: Arc::downgrade(queue),
|
||||||
|
accounts: Arc::downgrade(accounts),
|
||||||
client: Arc::downgrade(client),
|
client: Arc::downgrade(client),
|
||||||
miner: Arc::downgrade(miner),
|
miner: Arc::downgrade(miner),
|
||||||
}
|
}
|
||||||
@ -71,9 +73,18 @@ impl<C, M> EthSigning for EthSigningQueueClient<C, M>
|
|||||||
fn send_transaction(&self, params: Params) -> Result<Value, Error> {
|
fn send_transaction(&self, params: Params) -> Result<Value, Error> {
|
||||||
from_params::<(TransactionRequest, )>(params)
|
from_params::<(TransactionRequest, )>(params)
|
||||||
.and_then(|(mut request, )| {
|
.and_then(|(mut request, )| {
|
||||||
let queue = take_weak!(self.queue);
|
let accounts = take_weak!(self.accounts);
|
||||||
let (client, miner) = (take_weak!(self.client), take_weak!(self.miner));
|
let (client, miner) = (take_weak!(self.client), take_weak!(self.miner));
|
||||||
|
|
||||||
|
if accounts.is_unlocked(request.from) {
|
||||||
|
let sender = request.from;
|
||||||
|
return match sign_and_dispatch(&*client, &*miner, request, &*accounts, sender) {
|
||||||
|
Ok(hash) => to_value(&hash),
|
||||||
|
_ => to_value(&H256::zero()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let queue = take_weak!(self.queue);
|
||||||
fill_optional_fields(&mut request, &*client, &*miner);
|
fill_optional_fields(&mut request, &*client, &*miner);
|
||||||
let id = queue.add_request(request);
|
let id = queue.add_request(request);
|
||||||
let result = id.wait_with_timeout();
|
let result = id.wait_with_timeout();
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use std::str::FromStr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use jsonrpc_core::IoHandler;
|
use jsonrpc_core::IoHandler;
|
||||||
use v1::impls::EthSigningQueueClient;
|
use v1::impls::EthSigningQueueClient;
|
||||||
@ -21,12 +22,16 @@ use v1::traits::EthSigning;
|
|||||||
use v1::helpers::{ConfirmationsQueue, SigningQueue};
|
use v1::helpers::{ConfirmationsQueue, SigningQueue};
|
||||||
use v1::tests::helpers::TestMinerService;
|
use v1::tests::helpers::TestMinerService;
|
||||||
use util::{Address, FixedHash};
|
use util::{Address, FixedHash};
|
||||||
|
use util::numbers::{Uint, U256};
|
||||||
|
use ethcore::account_provider::AccountProvider;
|
||||||
use ethcore::client::TestBlockChainClient;
|
use ethcore::client::TestBlockChainClient;
|
||||||
|
use ethcore::transaction::{Transaction, Action};
|
||||||
|
|
||||||
struct EthSigningTester {
|
struct EthSigningTester {
|
||||||
pub queue: Arc<ConfirmationsQueue>,
|
pub queue: Arc<ConfirmationsQueue>,
|
||||||
pub client: Arc<TestBlockChainClient>,
|
pub client: Arc<TestBlockChainClient>,
|
||||||
pub miner: Arc<TestMinerService>,
|
pub miner: Arc<TestMinerService>,
|
||||||
|
pub accounts: Arc<AccountProvider>,
|
||||||
pub io: IoHandler,
|
pub io: IoHandler,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,13 +40,15 @@ impl Default for EthSigningTester {
|
|||||||
let queue = Arc::new(ConfirmationsQueue::default());
|
let queue = Arc::new(ConfirmationsQueue::default());
|
||||||
let client = Arc::new(TestBlockChainClient::default());
|
let client = Arc::new(TestBlockChainClient::default());
|
||||||
let miner = Arc::new(TestMinerService::default());
|
let miner = Arc::new(TestMinerService::default());
|
||||||
|
let accounts = Arc::new(AccountProvider::transient_provider());
|
||||||
let io = IoHandler::new();
|
let io = IoHandler::new();
|
||||||
io.add_delegate(EthSigningQueueClient::new(&queue, &client, &miner).to_delegate());
|
io.add_delegate(EthSigningQueueClient::new(&queue, &client, &miner, &accounts).to_delegate());
|
||||||
|
|
||||||
EthSigningTester {
|
EthSigningTester {
|
||||||
queue: queue,
|
queue: queue,
|
||||||
client: client,
|
client: client,
|
||||||
miner: miner,
|
miner: miner,
|
||||||
|
accounts: accounts,
|
||||||
io: io,
|
io: io,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -78,5 +85,41 @@ fn should_add_transaction_to_queue() {
|
|||||||
// then
|
// then
|
||||||
assert_eq!(tester.io.handle_request(&request), Some(response.to_owned()));
|
assert_eq!(tester.io.handle_request(&request), Some(response.to_owned()));
|
||||||
assert_eq!(tester.queue.requests().len(), 1);
|
assert_eq!(tester.queue.requests().len(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_dispatch_transaction_if_account_is_unlocked() {
|
||||||
|
// given
|
||||||
|
let tester = eth_signing();
|
||||||
|
let acc = tester.accounts.new_account("test").unwrap();
|
||||||
|
tester.accounts.unlock_account_permanently(acc, "test".into()).unwrap();
|
||||||
|
|
||||||
|
let t = Transaction {
|
||||||
|
nonce: U256::zero(),
|
||||||
|
gas_price: U256::from(0x9184e72a000u64),
|
||||||
|
gas: U256::from(0x76c0),
|
||||||
|
action: Action::Call(Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap()),
|
||||||
|
value: U256::from(0x9184e72au64),
|
||||||
|
data: vec![]
|
||||||
|
};
|
||||||
|
let signature = tester.accounts.sign(acc, t.hash()).unwrap();
|
||||||
|
let t = t.with_signature(signature);
|
||||||
|
|
||||||
|
// when
|
||||||
|
let request = r#"{
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"method": "eth_sendTransaction",
|
||||||
|
"params": [{
|
||||||
|
"from": ""#.to_owned() + format!("0x{:?}", acc).as_ref() + r#"",
|
||||||
|
"to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
|
||||||
|
"gas": "0x76c0",
|
||||||
|
"gasPrice": "0x9184e72a000",
|
||||||
|
"value": "0x9184e72a"
|
||||||
|
}],
|
||||||
|
"id": 1
|
||||||
|
}"#;
|
||||||
|
let response = r#"{"jsonrpc":"2.0","result":""#.to_owned() + format!("0x{:?}", t.hash()).as_ref() + r#"","id":1}"#;
|
||||||
|
|
||||||
|
// then
|
||||||
|
assert_eq!(tester.io.handle_request(&request), Some(response.to_owned()));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user