Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Commit

Permalink
feat: add evm_unlockUnknownAccount (#630)
Browse files Browse the repository at this point in the history
Co-authored-by: Aaryamann Challani <aaryamannchallani7@gmail.com>
  • Loading branch information
davidmurdoch and rymnc committed Sep 15, 2020
1 parent 28048eb commit 5c173fa
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 0 deletions.
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,30 @@ Special non-standard methods that aren’t included within the original RPC spec
```json
{ "id": 1337, "jsonrpc": "2.0", "result": "0x0" }
```
* `evm_unlockUnknownAccount` : Unlocks any unknown account. Accounts known to the `personal` namespace and accounts
returned by `eth_accounts` cannot be unlocked using this method; use `personal_lockAccount` instead.
```bash
# Ex: account: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
curl -H "Content-Type: application/json" -X POST --data \
'{"id":1337,"jsonrpc":"2.0","method":"evm_unlockUnknownAccount","params":["0x742d35Cc6634C0532925a3b844Bc454e4438f44e"]}' \
http://localhost:8545
```
```json
{ "id": 1337, "jsonrpc": "2.0", "result": true }
```
* `evm_lockUnknownAccount` : Locks any unknown account. Accounts known to the `personal` namespace and accounts
returned by `eth_accounts` cannot be locked using this method; use `personal_unlockAccount` instead.
```bash
# Ex: account: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
curl -H "Content-Type: application/json" -X POST --data \
'{"id":1337,"jsonrpc":"2.0","method":"evm_lockUnknownAccount","params":["0x742d35Cc6634C0532925a3b844Bc454e4438f44e"]}' \
http://localhost:8545
```
```json
{ "id": 1337, "jsonrpc": "2.0", "result": true }
```
## Unsupported Methods
Expand Down
59 changes: 59 additions & 0 deletions lib/subproviders/geth_api_double.js
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,65 @@ GethApiDouble.prototype.evm_mine = function(timestamp, callback) {
// indicate that `evm_mine` only requires one argument (the callback)
GethApiDouble.prototype.evm_mine.minLength = 1;

/**
* Unlocks any unknown account.
*
* Note: accounts known to the `personal` namespace and accounts returned by
* `eth_accounts` cannot be unlocked using this method.
*
* @param {*} address the address of the account to unlock
* @param {*} callback
* @returns `true` if the account was unlocked successfully, `false` if the
* account was already unlocked. Throws an error if the account could not be
* unlocked.
*/
GethApiDouble.prototype.evm_unlockUnknownAccount = function(address, callback) {
// check if given address is already unlocked
address = address.toLowerCase();
if (this.state.unlocked_accounts[address] !== true) {
if (this.state.personal_accounts[address] !== true) {
// unlock the account
this.state.unlocked_accounts[address] = true;
return callback(null, true);
} else {
// if the account is known to the `personal` namespace we may not unlock
// it
return callback(new Error("cannot unlock known/personal account"));
}
}
// account was already unlocked, return `false`
callback(null, false);
};

/**
* Locks any unknown account.
*
* Note: accounts known to the `personal` namespace and accounts returned by
* `eth_accounts` cannot be locked using this method.
*
* @param {*} address the address of the account to lock
* @param {*} callback
* @returns `true` if the account was locked successfully, `false` if the
* account was already locked. Throws an error if the account could not be
* locked.
*/
GethApiDouble.prototype.evm_lockUnknownAccount = function(address, callback) {
// Checks if given address is already unlocked
address = address.toLowerCase();
if (this.state.unlocked_accounts[address]) {
if (this.state.personal_accounts[address]) {
// if the account is known to the `personal` namespace we may not lock it
return callback(new Error("cannot lock known/personal account"));
} else {
// unlock the account
delete this.state.unlocked_accounts[address];
return callback(null, true);
}
}
// account wasn't locked to begin with, return `false`
callback(null, false);
};

GethApiDouble.prototype.debug_traceTransaction = function(txHash, params, callback) {
if (typeof params === "function") {
callback = params;
Expand Down
75 changes: 75 additions & 0 deletions test/local/accounts.js
Original file line number Diff line number Diff line change
Expand Up @@ -285,4 +285,79 @@ describe("Accounts", () => {
await runTests(false);
});
});

describe("evm_lockUnknownAccount/evm_unlockUnknownAccount", () => {
let accounts, send;
before(async() => {
const context = await initializeTestProvider();
accounts = context.accounts;
send = context.send;
});

it("should unlock any account after server has been started", async() => {
const address = "0x742d35Cc6634C0532925a3b844Bc454e4438f44e";
const { result: result1 } = await send("evm_unlockUnknownAccount", address);
assert.strictEqual(result1, true);

// should return `false` if account was already locked
const { result: result2 } = await send("evm_unlockUnknownAccount", address);
assert.strictEqual(result2, false);
});

it("should not unlock any locked personal account", async() => {
const [address] = accounts;
await send("personal_lockAccount", address);
try {
await assert.rejects(
send("evm_unlockUnknownAccount", {
message: "cannot unlock known/personal account"
})
);
} finally {
// unlock the account
await send("personal_unlockAccount", address, "", 0);
}
});

it("should lock any unlocked unknown account via evm_lockUnknownAccount", async() => {
const address = "0x842d35Cc6634C0532925a3b844Bc454e4438f44f";
const { result: unlockResult } = await send("evm_unlockUnknownAccount", address);
assert.strictEqual(unlockResult, true);

const { result: lockResult1 } = await send("evm_lockUnknownAccount", address);
assert.strictEqual(lockResult1, true);

// bonus: also make sure we return false when the account is already locked:
const { result: lockResult2 } = await send("evm_lockUnknownAccount", address);
assert.strictEqual(lockResult2, false);
});

it("should not lock a known account via evm_lockUnknownAccount", async() => {
await assert.rejects(
send("evm_lockUnknownAccount", accounts[0], {
message: "cannot lock known/personal account"
})
);
});

it("should not lock a personal account via evm_lockUnknownAccount", async() => {
// create a new personal account
const { result: address } = await send("personal_newAccount", "password");

// then explicitly unlock it
const { result } = await send("personal_unlockAccount", address, "password", 0);
assert.strictEqual(result, true);

// then try to lock it via evm_lockUnknownAccount
await assert.rejects(send("evm_lockUnknownAccount", address), {
message: "cannot lock known/personal account"
});
});

it("should return `false` upon lock if account isn't locked (unknown account)", async() => {
const address = "0x942d35Cc6634C0532925a3b844Bc454e4438f450";
const { result } = await send("evm_lockUnknownAccount", address);
assert.strictEqual(result, false);
});
});
});

0 comments on commit 5c173fa

Please sign in to comment.