ethereum / interfaces

Interface Specifications inside Ethereum
36 stars 175 forks source link

"account" RPC API over IPC for standalone signer. #15

Open frozeman opened 7 years ago

frozeman commented 7 years ago

Abstract

This is the API for a standalone signer daemon, which will handle private keys and signing and deliver support for HD and hardware wallets. This daemon will have its own IPC connection and will be separate from any running node.

NOTE This is API v 1.0 for a signer daemon without UI!

Connection

JSON RPC 2.0 over IPC.

This signer should open its own IPC connection. e.g. on ~/Library/Ethereum/signer.ipc

Binary flags

--datadir /path/to/keystore

API

IN PROGRESS

account_list ( )
> [{
        type: "account |hd|ledger|trezor",
        url: "...",
        accounts: ['0x234567','0x2134567'] // maybe HD path?
    }, {
      ...
    }]
account_new ( string: password) 
> {
        id: 0,
        type: "account|hd|ledger|trezor",
        url: "...",
        accounts: ['0x234567'] // only one for "normal" accounts
    }
account_newHDWallet ( string: newPassword ) 
> {
        id: 0,
        type: "account|hd|ledger|trezor",
        url: "...",
        mnemonic: "hello world iam here ...",
        accounts: ['0x234567'] // first account generated
    }
account_newHDWallet ( string: newPassword ) 
> {
        id: 0,
        type: "account|hd|ledger|trezor",
        url: "...",
        mnemonic: "hello world iam here ...",
        accounts: ['0x234567'] // first account generated
    }
account_getHDWalletAddress ( string: id, number: index?? ) 
> 0x1234567654321234567...
account_export ( string: address|id|publicKey)  // works also of HD wallets
> { web3 keystore json }
account_import ( Object: web3 keystore json) 
>  {
        id: 0,
        type: "account|hd|ledger|trezor",
        url: "...",
        mnemonic: "hello world iam here ...",
        accounts: ['0x234567', '0x234567', '0x234567']
    }
account_importPrivateKey (string privateKey)
> {
        id: 0,
        url: "...",
        type: "account|hd|ledger|trezor",
        accounts: ['0x234567']
    }
account_signTransaction (object: txObject, array: JSONInterface, string: password)
> 0x123456789876543212345678..
// OR
> {
   hash: '0x234567890',
   r: '0x456789',
   s: '0x234678',
   v: '0x02',
   signature: '0x1234567654321234567' // full RLP encoded signature, passable to eth_sendRawTransaction
}
account_sign (string: message, array: JSONInterface, string: password)
> 0x123456789876543212345678..
// OR
> {
   message: 'Hello',
   hash: '0x234567890',
   r: '0x456789',
   s: '0x234678',
   v: '0x02',
   signature: '0x1234567654321234567' // full signature, passable to personal_ecRecover
}
account_recover (string/Object: RLPencodedsig|ObjectWithSignatureValues)
> '0x23456789876543212' // Ethereum address

// Is the below needed, or can "is transaction" be auto detected in "personal_recover"

account_recoverTransaction (string/Object: RLPencodedsig|ObjectWithSignatureValues)
> '0x23456789876543212' // Ethereum address
account_unlock (string: address|id|publicKey, string: password)
> true
account_lock (string: address|id|publicKey)
> true

Addition we could add support for subscriptions for key adding etc.

frozeman commented 7 years ago

I would actually propose too to change the namespace from personal to account, as this is more specific.

Then we can also make some functions shorter like personal_unlockAccount to account_unlock

danfinlay commented 7 years ago

I like the idea of exposing some methods for requesting the signer create new accounts, but I don't like the idea of the signer returning private information in response to that.

Imagine a website, asking "create a new account for use with us", and then handing them the private keys. That doesn't sound very secure.

I like your idea about an account namespace, but since personal is established, to avoid breaking APIs, I'd prefer either:

frozeman commented 7 years ago

Ok maybe to clarify. This Proposal was created after a debate in the go team about adding a separate signer instance, with its own IPC connection.

This will be additional to the personal endpoint (which might be deprecated at some point) and will not be part of the node, but a separate process with separate IPC connection. Dapps like IN Mist won't have access to this API, but Dapps LIKE Mist will. This will be the main signer for native dapps to use, and receiving private information will only be available on functions where you need to provide a password ;)

So This wont be part of default web3, as Dapps can't connect to this IPC endpoint.

holiman commented 7 years ago

Why would these be needed:

Generally, I don't understand why we'd design the API to let the caller handle a lot of sensitive stuff. I'd want the signer to take on the security responsibilities, so that callers can concentrate on things not related to private keys, passwords, signing. That means that the signer should expose methods like

frozeman commented 7 years ago

As we extensively discussed the signer wont have any UI for now, we can always change the API later once a signer with UI comes around.

As long as that is not the case the native dapp need to be able to present the mnemonic phrase to the user. We also should be aware that this is not a user interface, but a developer API. So we surely need ways to export and import, retrieve keys, etc. It also should look the Mist/custom dapp way, as long as we don't have a signer UI.

Besides when generating there always need to be a password send along to get this secrets like privatekys, so its not that they are exposed over that API for everybody.

bas-vk commented 7 years ago

In the long run I agree with @holiman that the signer should handle all sensitive data even if that means that Mist has to make sacrifices to its user experience.

The protocol will be json rpc 2.0 with the same conventions as the rpc interface has (e.g. hex encoding, data must be a multiple of 2)? The examples json message are not valid json rpc 2.0 messages.

What is the purpose of the key id? We have something for non-hardware devices. But I'm not sure if hardware tokens also have something like that. Maybe just remove it?

I also think that the singer should have support for notifications. Hardware tokens can be plugged in/out at will and the singer should be able to inform its clients of such events.

account_signTransaction: maybe the api should not accept returnRLPEncoded and always return an RLP encoded transaction that can be send with eth_sendRawTransaction. I'm also thinking if this method should accept an argument to indicate which signing algorithm should be used. Recently eip 155 was introduced that prevents replay attacks. Some hardware tokens might not have support for it, or only after a particular firmware version. It would be nice if the client has the ability to specify a signing algorithm version and get an error if the signer was not able to meet these requirements.

frozeman commented 7 years ago

@bas-vk