Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support DApp signing #23

Open
2 tasks
Keith-CY opened this issue May 28, 2022 · 29 comments
Open
2 tasks

Support DApp signing #23

Keith-CY opened this issue May 28, 2022 · 29 comments
Assignees
Labels

Comments

@Keith-CY
Copy link
Member

Keith-CY commented May 28, 2022

  • watch wallet of web app(connect to neuron)
    • web app subscribe addresses to neuron/requests xpub key from neuron to generate watch-only wallet
  • signing with native message
    • web app generate a transaction and requests a sign from neuron, after signing, neuron will send the witnesses to web app via url
@Keith-CY Keith-CY self-assigned this May 28, 2022
@Keith-CY
Copy link
Member Author

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
Copy link
Member Author

Keith-CY commented May 30, 2022

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
Loading

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
Loading

@Keith-CY
Copy link
Member Author

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

  • Neuron for signing and submitting a transaction
  • Explorer for providing data(live cells, statistics)
  • Dapp for generating transactions of business logic

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
Copy link

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
Copy link
Member Author

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
Copy link

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
Copy link
Member Author

Keith-CY commented May 31, 2022

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

  • technical stack: enable custom protocol with an MVP
  • protocol between dapp and neuron: how to serialize tx to sign, raw transaction structure from ckb rfc, or structured transaction as eip712, or limited transaction types are allowed
  • how to represent the transaction to sign: reuse offline sign tx? add a brand new UI?
  • what else data could be exposed: like xpub wallet?
  • how many functionalities should be delivered with the web wallet: track balances and assets, view history, generate basic transactions, deposit to layer2, add ckb price?
  • necessary API from explorer: get live cells, get history

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
Copy link
Member Author

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
Copy link

yanguoyu commented Jun 7, 2022

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
protocol.mov
  1. registerFileProtocol
file-protocol.mov

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

@Keith-CY
Copy link
Member Author

Keith-CY commented Jun 7, 2022

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
Copy link
Member Author

Keith-CY commented Jun 7, 2022

@yanguoyu
Copy link

yanguoyu commented Jun 9, 2022

APIs:

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

@Keith-CY
Copy link
Member Author

Keith-CY commented Jun 9, 2022

APIs:

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

good point

@Keith-CY
Copy link
Member Author

Keith-CY commented Jun 9, 2022

APIs:

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

Can setAsDefaultProtocolClient verify source of requests?

@yanguoyu
Copy link

yanguoyu commented Jun 9, 2022

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
Copy link
Member Author

Keith-CY commented Jun 9, 2022

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
Copy link

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
Copy link
Member Author

Keith-CY commented Jun 10, 2022

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
Loading

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
Loading

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
Copy link

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
Copy link
Member Author

Keith-CY commented Jun 15, 2022

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.

@Keith-CY Keith-CY reopened this Jun 15, 2022
@yanguoyu
Copy link

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
Copy link
Member Author

Keith-CY commented Jun 15, 2022

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 #23 (comment) 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
Copy link

yanguoyu commented Jul 5, 2022

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
Copy link

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
Copy link
Member Author

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
Copy link

yanguoyu commented Aug 8, 2022

  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'
}
  1. 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 Keith-CY removed this from the 2022/06/15 - 2022/06/22 milestone Nov 30, 2022
@Keith-CY
Copy link
Member Author

Keith-CY commented Apr 3, 2023

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
Copy link
Member Author

Keith-CY commented Apr 28, 2023

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
Copy link
Member Author

Tracked by 3 individual issues:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: 📌Planning
Status: Hold on
Development

No branches or pull requests

2 participants