Magickbase / neuron-public-issues

Neuron Issues
6 stars 3 forks source link

Support DApp signing #23

Open Keith-CY opened 2 years ago

Keith-CY commented 2 years ago
Keith-CY commented 2 years ago

Please do some technical investigation about native messaging(such as custom protocol of electron, native messaging of web extension) between web app and electron app, which enables a web app to communicate with neuron via IPC.

With native messaging, we can empower a web app to track user's assets in watch wallet mode and request a sign for transactions.

Ref: https://www.electronjs.org/docs/latest/tutorial/launch-app-from-url-in-another-app Ref: https://www.electronjs.org/docs/latest/api/protocol Ref: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging

Keith-CY commented 2 years ago

watch-only wallet

sequenceDiagram
  participant web app
  participant neuron
  participant ckb explorer
  web app->>neuron: request xpub key[native messaging]
  neuron->>web app: xpub key[opening url]
  web app->>ckb explorer: all derived addresses
  ckb explorer->>web app: balances, live cells, tx history
  web app->>web app: feature-rich UI

sign transaction

sequenceDiagram
  participant web app
  participant neuron
  participant ckb explorer
  web app->>ckb explorer: all derived addresses
  ckb explorer->>web app: live cells
  web app->>web app: generate a tx
  web app->>neuron: request a sign and submit[native messaging]
  neuron->>web app: tx hash[opening url]
  web app->>ckb explorer: tx hash
  ckb explorer->>web app: tx status
Keith-CY commented 2 years ago

Workflow of neuron, dapp, and explorer is appended above.

With this workflow, we can provide a powerful web wallet as image

The key problem here is the protocol between dapp and neuron, namely, have to transfer message from dapp and neuron.

For now, I get two

  1. nativeMessage of web extension, which proxy messages from web app to native application, a bit complex but an extra web extension can be delivered together.
  2. custom protocol of electron, seems to be easy, more investigation is needed.

How do you think about them @yanguoyu @qiweiii

yanguoyu commented 2 years ago

https://github.com/nervosnetwork/keypering support sign DApp, can we refer to it? nativeMessage is really complex, I have no experience with web extension. But it may support more features. If we want to explore more with web extension, I think it's a good idea. Or should we only use custom protocol or HTTP protocol?

Keith-CY commented 2 years ago

nervosnetwork/keypering support sign DApp, can we refer to it? nativeMessage is really complex, I have no experience with web extension. But it may support more features. If we want to explore more with web extension, I think it's a good idea. Or should we only use custom protocol or HTTP protocol?

Keypering uses RPC for communication because it allows bidirectional messaging and less consideration on safety. But neuron won't expose an endpoint of RPC so native messaging is required.

I also prefer custom protocol since it's unidirectional natively for safety and custom protocol is supported by the operating system so there is potential to communicate with other applications.

yanguoyu commented 2 years ago

send the witnesses to web app via url

Should change to send the tx_hash to web app via url?

In addition, how can we cooperate to finish this task?

Keith-CY commented 2 years ago

Should change to send the tx_hash to web app via url?

Yes, tx hash should be sent back as an index, witnesses could be sent back when neuron only does the signing work but doesn't commit the tx to ckb node(neuron could disconnect to a node).

In addition, how can we cooperate to finish this task?

We'd better finish research first, including

Once the technical design and product design are done, tasks will be split into chunks, maybe as follows,

  1. handle-custom-protocol controller/service
  2. UI of signing tx from dapp
  3. necessary API from explorer for a web wallet
  4. a simple web wallet

Until then we can estimate how many works to do and how to cooperate with each other

Keith-CY commented 2 years ago

For protocol between dapp and neuron, limited transaction types is preferred personally, and I expect other teams to propose their transaction type to enrich neuron.

yanguoyu commented 2 years ago

Use custom protocol like this? It uses https://www.electronjs.org/docs/latest/api/app#appsetasdefaultprotocolclientprotocol-path-args. I found the protocol defined by https://www.electronjs.org/docs/latest/api/protocol seem only use in electron app, but not on the website.

  1. setAsDefaultProtocolClient

https://user-images.githubusercontent.com/12881040/172315312-8ec34e06-241c-4b02-a226-3dd2768fbb7c.mov

  1. registerFileProtocol

https://user-images.githubusercontent.com/12881040/172316486-dc0bd910-aed9-4a6b-b694-9f819515594e.mov

reference: https://shipshape.io/blog/launch-electron-app-from-browser-custom-protocol/

Keith-CY commented 2 years ago

Use custom protocol like this? It uses electronjs.org/docs/latest/api/app#appsetasdefaultprotocolclientprotocol-path-args. I found the protocol defined by electronjs.org/docs/latest/api/protocol seem only use in electron app, but not on the website.

  1. setAsDefaultProtocolClient

    protocol.mov

  2. registerFileProtocol

    file-protocol.mov reference: shipshape.io/blog/launch-electron-app-from-browser-custom-protocol

The first looks good to me.

After reading the docs I got that protocol module in electron works within BrowserWindow and has no effect outside the electron app.

Keith-CY commented 2 years ago

Protocols to have a look at:

  1. eip 712: https://eips.ethereum.org/EIPS/eip-712
  2. eip 2255: https://github.com/ethereum/EIPs/issues/2255
  3. keypering https://talk.nervos.org/t/keyper-agency-remote-procedure-call-specification/5827
  4. wallet authorization https://talk.nervos.org/t/rfc-wallet-authorization-spec-proposal/4962
  5. web auth https://talk.nervos.org/t/abc-wallet-another-ckb-sdk-and-ckb-web-auth/4285

APIs required:

  1. get xpub
  2. sign message/txn
yanguoyu commented 2 years ago

APIs:

  1. registerDapp: let the user know how many Dapp has registered and avoid unregistering requests.
Keith-CY commented 2 years ago

APIs:

  1. registerDapp: let the user know how many Dapp has registered and avoid unregistering requests.

good point

Keith-CY commented 2 years ago

APIs:

  1. registerDapp: let the user know how many Dapp has registered and avoid unregistering requests.

Can setAsDefaultProtocolClient verify source of requests?

yanguoyu commented 2 years ago

APIs:

  1. registerDapp: let the user know how many Dapp has registered and avoid unregistering requests.

Can setAsDefaultProtocolClient verify source of requests?

We can add verification when opening the app by the default protocol with some parameters.

Keith-CY commented 2 years ago

APIs:

  1. registerDapp: let the user know how many Dapp has registered and avoid unregistering requests.

Can setAsDefaultProtocolClient verify source of requests?

We can add verification when opening the app by the default protocol with some parameters.

The source can be fabricated if it's specified by dapps but not by their hosts, say, website A sends a request with a declaration that it's website B, we cannot verify it.

Maybe we can avoid a verification before handling the request, instead, we display the declared source with the request to users, and send the response to the declared source. By this way, the website A disguises itself as website B cannot get the response.

Also, we don't need an extra API registerDapp to know which dapps are allowed, we can do the registration on their requests' arrival.

yanguoyu commented 2 years ago

The register should be a simple operation to check. Then when calling other APIs, users know it must be from safety Dapp. Or else the user needs to check the current transaction or message is correct, and check them is complex.

And maybe we can't get the host information. we can only get the request URL from the source.

Keith-CY commented 2 years ago

The register should be a simple operation to check. Then when calling other APIs, users know it must be from safety Dapp. Or else the user needs to check the current transaction or message is correct, and check them is complex.

We can check dapp's registration automatically before displaying the tx on their first request of data

sequenceDiagram
  autonumber
  participant DApp
  participant Neuron
  DApp->>Neuron: Request data
  Neuron->>Neuron: Register DApp
  Neuron->>DApp: Respond data

instead of sending register dapp before request data

sequenceDiagram
  autonumber
  participant DApp
  participant Neuron
  DApp->>Neuron: Register DApp
  Neuron->>DApp: Registered
  DApp->>Neuron: Request data
  Neuron->>DApp: Respond data

And maybe we can't get the host information. we can only get the request URL from the source.

It would be enough if the request URL is in event object provided by the system.

yanguoyu commented 2 years ago

We can check dapp's registration automatically before displaying the tx on their first request of data

How do we check dapp's registration automatically?

we can only get the request URL from the source.

Maybe my description is mistake. I mean we can only get the URL that includes customer protocol and parameters. eg: <a href="protocol-test://a=1&b=2&c=4">open with neuron</a>, href is the URL we can get in neuron.

Keith-CY commented 2 years ago

How do we check dapp's registration automatically?

Neuron will have a table recording interacted DApps and marks them registered | blocked. Once DApp A sends a message to Neuron first time, it cannot be found in the table and Neuron will prompt a registration request to user. If registration is done, Neuron marks the DApp registered and shows the message to the user. Next time the DApp sends a message to Neuron, it could be found in the table and the message can be handled directly.

Maybe my description is mistake. I mean we can only get the URL that includes customer protocol and parameters. eg: open with neuron, href is the URL we can get in neuron.

The href can be any data specified by the DApp so it is not a trustful dapp source. Similar to phishing emails, the email sender can declare itself as a well-known organization without validation and requires you to respond with sensitive information, like, a verification code. So almost all confirmation emails include a login URL with authentication for user to check if the URL is correct.

We can do it similarly, with a source URL displaying to the user and sends a response to the URL user has checked, instead of verifying the source of the message.

yanguoyu commented 2 years ago

We can do it similarly, with a source URL displaying to the user and sends a response to the URL user has checked, instead of verifying the source of the message.

yeah, href is not a trustful Dapp source. And source URL is a good display for the user. But we seem can't to get the source URL.

Keith-CY commented 2 years ago

We can do it similarly, with a source URL displaying to the user and sends a response to the URL user has checked, instead of verifying the source of the message.

yeah, href is not a trustful Dapp source. And source URL is a good display for the user. But we seem can't to get the source URL.

I didn't make it clear.

Similar to handling authentication URL in emails, users don't have to care about the email senders.

Neuron accepts the URLs declared in messages, even that they are not consistent with the sources, and sends responses to the declared URLs, instead of verifying the sources of messages.

It's a reply to add verification when opening the app in https://github.com/Magickbase/neuron-public-issues/issues/23#issuecomment-1151008739 and I may misunderstand the verification in the comment. I thought it was related to checking if the message source is trustful, but the real purpose may be checking if the declared URL is in the whitelist.

yanguoyu commented 2 years ago

Keypering uses RPC for communication because it allows bidirectional messaging and less consideration on safety. But neuron won't expose an endpoint of RPC so native messaging is required.

I also prefer custom protocol since it's unidirectional natively for safety and custom protocol is supported by the operating system so there is potential to communicate with other applications.

keypering start a local server to accept Dapp request, And it also uses auth for authentication and authorization. I don't know what do you means bidirectional messaging. I reconsider a local rpc or HTTP server because it can make API easy. setAsDefaultProtocolClient can only open Neuron and receive messages from DApp, but it can't send message to DApp.

yanguoyu commented 2 years ago

I have created a repository to test DApp sign with Neuron. I found it seems to have no length limit for open custom protocol. So I think we can send more detailed information to Neuron. And we only send added property back to DApp by callback URL. Then we can start discussing the definition of the interface.

I have written a simple definition of it, it will be perfect later.

request params

{
  requestId: uuid
  appName: string
  type: 'sign_message' | 'sign_transaction'
  params: tx | message
  callback: string
}

result

{
  code: number
  err: string
  requestId: uuid
  result: any
  hash: string // for validation message is not lost
}
Keith-CY commented 2 years ago

I have created a repository to test DApp sign with Neuron. I found it seems to have no length limit for open custom protocol. So I think we can send more detailed information to Neuron. And we only send added property back to DApp by callback URL. Then we can start discussing the definition of the interface.

I have written a simple definition of it, it will be perfect later.

request params

{
  requestId: uuid
  appName: string
  type: 'sign_message' | 'sign_transaction'
  params: tx | message
  callback: string
}

result

{
  code: number
  err: string
  requestId: uuid
  result: any
  hash: string // for validation message is not lost
}
  1. adding a version field could facilitate API migration;
  2. is it necessary to add a chain type field for additional verification so users will be told explicitly the signed tx is going to be submitted to the mainnet or testnet. What's more, when the user clicks on sign and send, it will be stopped if target chain is not the connected one.
yanguoyu commented 2 years ago
  1. request params Request params should be encoded by encodeURIComponent
    {
    requestId: uuid
    appName: string
    type: 'sign_message' | 'sign_transaction'
    tx?: {
    cell_deps: {
        out_point: {
          tx_hash: string
          index: string
        }
        dep_type: string
    }[]
    header_deps: string[]
    inputs: {
        previous_output: {
            index: string
            tx_hash: string
        }
        since: string
    }[]
    outputs: {
        capacity: string
      lock: {
        args: string
        code_hash: string
        hash_type: 'type' | 'data'
      },
      type: string | null
    }[]
    outputs_data: string[]
    version: string
    }
    message?: string
    callback: string
    version: string
    chain: 'mainnet' | 'testnet'
    }
  2. result Result will also be encoded by encodeURIComponent
    {
    code: number
    err: string
    requestId: uuid
    result: {
    witnesses: string[]
    }
    hash: string // for validation message is not lost
    }
Keith-CY commented 1 year ago

We may work with Nexus team to promote the protocol, but Nexus is not ready yet in the protocol level, this issue will be re-activated later.

Please ping us when you're ready @homura

Keith-CY commented 1 year ago

Reactivate this issue and expand the scope to

  1. define a protocol between neuron/wallet and dapp, the protocol should be compatible with https://github.com/ckb-js/nexus/tree/main/packages/protocol
  2. propose some specs in
    blockchain reference/id: https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2.md
    account reference: https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-10.md
    asset reference(sudt/cota…): https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-19.md
    sign-in-with-x: https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-122.md
  3. integrate with walletconnect to work with dapp
  4. work with dapp by system native message
Keith-CY commented 1 year ago

Tracked by 3 individual issues: