uPort on any Ethereum blockchain

Why uPort Supports Multiple Networks & Application Accounts

Along time ago, in a galaxy far, far away, a single production Ethereum network and a single testnet existed. These were called Mainnet and Morden. Then the homestead update of Ethereum came out, which required an updated testnet, so Ropsten replaced Morden. After some time Ropsten started getting spammed, which out of necessity brought about more testnets, called Kovan and Rinkeby. On the Mainnet front, we had the DAO hack, which also caused a hard fork which wasn’t a planned protocol update. Some chose not to support this hard fork, giving rise to Ethereum classic.

A Growing Number of Ethereum Blockchains

One thing is for certain in this evolving landscape. Multiple Ethereum blockchains will exist — currently the total is 5 public Ethereum blockchains. Private Ethereum chains are being used as well. For developers and users alike it’s a matter of fact — we must get used to a world with multiple Ethereum networks.

However, that means our technology infrastructure and decentralized applications, must take this into account because the alternative is a diminished user experience.

To add even more complexity into the mix, blockchain bridges will also be a thing — so you might run different parts of a decentralized application across a number of different blockchains… it’s going to get complicated.

Thank you Alex Miller from GridPlus+ for the proposed bridges.

Multi-Network Identifiers — A System to Manage Chains & Accounts

We introduced Multi-Network Identifiers (MNID’s) in April 2017

MNID is an encoding scheme to encode/decode public ethereum addresses and blockchain network ID. When the MNID is decoded, both the address and network ID become available. The address and network ID are used to determine who is sending the transaction and which network the transaction should be sent to.

MNID encoding Example address: 0x00521965e7bd230323c423d96c657db5b79d099f

networkId: “0x2a” //Kovan=0x2a, Rinkeby=0x4 output: 34ukSmiK1oA1C5Du8aWpkjFGALoH7nsHeDX

Let’s illustrate the problem. Today, if you send 1,000 ETH from your mainnet Ethereum address to purchase a token on the Ropsten or Kovan test network, that ETH essentially disappears. You’ve just lost 1,000 ETH and there isn’t really much anyone can do. This is true for all transactions sent to the wrong network. — Pelle Braendgaard

Ultimately it can be summarized into “mo networks mo problems.” The more networks (mainnet and testnets) users and developers interact with on a day-to-day basis, the more potential for errors and fatal mistakes.

“mo networks mo problems.”

With the introduction of MNID it was possible to elegantly manage application and network specific accounts within the uPort mobile app. In fact, shortly after introducing MNIDs the uPort team began experimenting with the idea of sub-accounts. During onboarding the users’ “root” account would be created on Rinkeby, afterwards they could create a single “sub-account” on each testnet they wanted to use. This created a proxy contract on the separate testnet for the user, and they could interact with smart contracts on these testnets. Ultimately it’s undesirable for a user to have to worry about which network they are on. However, for developers network flexibility is critical. So, the mobile app went through a new design iteration, and this functionality was temporarily removed. Now we have reintroduced it again and more in the “Accounts” screen.

The “more” is Multi Accounts

When an application wants to request information from a user, they now have a new capability. The application can specify an accountType field in the createRequest function of uport-js, and the requestCredentials function of uport-connect. This accountType field can be specified to be a few different things.

none - app does not return an ethereum address. Use this if all you want is to authenticate a user general — app behaves as usual, nothing new here keypair — app creates a regular ethereum keypair for use with only this app (no proxy) devicekey — This is used by an external account creation process to request a device key. See our upcoming private chain write up for more information segregated — creates account separate from the account created during onboarding, it has a different device address, different proxy address, and it could be on a different network (more on this in a bit)

The most relevent accountType for this section is the segregated account type. Upon the user’s approval of the selective disclosure request, the mobile app derives another keypair, and deploys another proxy contract. This is important because having separate Ethereum addresses, on a per-app basis, enables some level of privacy. Without this feature, all of a user’s on-chain interactions would happen through the one proxy made during onboarding or when creating a sub-account. This means anyone looking at their proxy address can see the users’ different on-chain interactions.

Accounts on any Ethereum network

The segregated account feature detailed above can also be done on a separate Ethereum network. For context, the uPort mobile app uses Rinkeby as the default network, and when the user goes through onboarding they are creating their identity on Rinkeby. This includes a public-private keypair and a proxy contract to represent the user. If an Ethereum application is not on Rinkeby, they can use this segregated account feature while specifying their network, to have the uPort mobile app create an account for the user.



To specify a network in a disclosure request in uport-js, you have to include a network_id parameter in the createRequest function. To do this in uport-connect, it uses the network defined when you instantiated the Connect object. This enables Ethereum Apps on any network to integrate uPort, have any uPort user interact with their app, all without the user needing to care about the network. The following example is for uport-js. If using uport-connect always remember it should only be used for experimentation or demo purposes and not in production!

uport-js example

const credentials = new Credentials({

appName: 'demo',

address: 'MNID goes here',

signer: signer,

networks: networksObject //networks supported by your app

})

credentials.createRequest({

network_id: '0x2a', //Kovan

accountType: 'segregated',

requested: ['name', 'avatar'],

notifications: true,

callbackUrl: 'https://callback' // URL to post the response to

}).then(requestToken => {

console.log(requestToken)

})

WAIT, but what about private chains?

There will be another article detailing this more, but some information will be provided here. This is where the accountType and network_id fields becomes important to talk about again. For network_id , you just choose a network id for your private chain (e.g. Kovan’s network ID is 0x2a). The accountType to use this time will be devicekey . Instead of triggering the mobile app to create a new uport account on one of the pre-defined public Ethereum networks, the mobile app will just create a new device key. Then the address of this key is included in the response to the disclosure request. This enables developers on private chains to use an external process to create the contracts necessary on their private chains. This includes one “Identity Manager”, one “claims registry”, and using the Identity Manager to deploy proxy contracts for device address.

Conclusion

Initially, the uPort app only interacted with Rinkeby. It created a proxy contract & DID Document for the user, and only allowed the user to interact with apps using the Rinkeby network. the feature was reintroduced allowing accounts on different networks to be created, enabling developers integrating uPort to use any Ethereum testnet. We augmented this feature by enabling developers to create Multi-Accounts, enhancing privacy for the user’s Ethereum interactions.