Skip to content

Instantly share code, notes, and snippets.

@hitripod
Created January 16, 2017 03:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hitripod/aebb2faa0ea60f1c3e2d1f7e6f03c194 to your computer and use it in GitHub Desktop.
Save hitripod/aebb2faa0ea60f1c3e2d1f7e6f03c194 to your computer and use it in GitHub Desktop.
uport deployment

uPort

說明

  1. uport-registryuport-proxy是合約的部署與web3.js操作介面library
  2. uport-persona 是uport的profile schema操作介面
    • 注意和uport-registry & uport-proxy 中的schema不同。
  3. uport-lib 是web application的library

主要的元件

  • Core uPort registry contract for linking attributes to uPort identities.

  • 需介接IPFS Service

  • 設定ipfsApi interface: uportRegistry.setIpfsProvider(ipfsApi(<hostname>, <port>));

  • 設定web3 interface: uportRegistry.setWeb3Provider(new web3.providers.HttpProvider('http://localhost:8545'));

  • UportRegistry.sol

     pragma solidity ^0.4.3;
     contract UportRegistry {
       event AttributesSet(address indexed _sender, uint _timestamp);
     
       uint public version;
       address public previousPublishedVersion;
     
       mapping(address => bytes) public ipfsAttributeLookup;
     
       function UportRegistry(address _previousPublishedVersion) {
         version = 1;
         previousPublishedVersion = _previousPublishedVersion;
       }
     
       function setAttributes(bytes ipfsHash) {
         ipfsAttributeLookup[msg.sender] = ipfsHash;
         AttributesSet(msg.sender, now);
       }
     
       function getAttributes(address personaAddress) constant returns(bytes) {
         return ipfsAttributeLookup[personaAddress];
       }
     }
    
  • Deploy

    • Deployed Transaction

    • Note: ConsenSys做的 ipfs-js 與 IPFS所做的 ipfs-api最新版本不合,注意要裝的是ipfs-api@2.3.2

    • 若使用testnet,修改 config.json:

       "testnet": {
       "web3Host": "139.162.75.109",
       "web3Port": "8545",
       "ipfsHost": "localhost",
       "ipfsPort": "5001",
       "ipfsWebPort": "8080",
       "uportRegistry": "0x0"
      },
      "selection": "testnet"
      
    • 若使用testnet,修改 deploy.js,需自行設定from_address & password:

       // Deploying a new PersonaRegistry
       //
       // Usage:
       // * modify app/javascripts/config.js so that selection
       //   is your target.
       // * node app/javascripts/deploy.js 0xaabbbcc
       //   where 0xaabbbcc is the address of the previous version
       //   of PersonaRegistry
       
       // Node modules
       var Persona     = require('./lib/uportregistry.js');
       var Web3        = require('web3');
       var Promise     = require('bluebird');
       var fs          = require('fs');
       
       // Data / Registries / Contracts
       var config = require('./config.json');
       console.log( config )
       
       // Web3 Instance
       var web3        = new Web3();
       
       // CLI Args
       var prevRegistryAddr = process.argv[2];
       var host     = config[config['selection']].web3Host;
       var web3port = 8545
       console.log(host)
       
       // Set Defaults
       if (host     === undefined) { host     = 'localhost'; }
       if (web3port === undefined) { web3port = '8545';      }
       
       // Make Providers
       var web3prov = new web3.providers.HttpProvider('http://' + host + ':' + web3port);
       
       const UportRegistry   = require('./build/contracts/UportRegistry.sol.js')
       
       // Set Providers
       web3.setProvider(web3prov);
       UportRegistry.setProvider(web3prov)
       
       var from_address = '<from_address>';
       var password = '<password>'
       web3.personal.unlockAccount(from_address, password);
       
       // Create new Persona Registry
       web3.eth.getAccounts(function(err, acct) {
       
         console.log('prev reg: ' + prevRegistryAddr)
         if (prevRegistryAddr === undefined) {
           prevRegistryAddr = '0x0000000000000000000000000000000000000000'
         }
       
         UportRegistry.new(prevRegistryAddr, {from: from_address, gas: 500000, gasPrice: 20000000000})
           .then(function(uportReg) {
             config[config['selection']].uportRegistry = uportReg.address;
             var output = JSON.stringify(config, null, 2) + '\n';
             fs.writeFile('./config.json', output);
             console.log('UportRegistry: ' + uportReg.address);
           })
      

});

	``` 
- setAttribute/getAttribute example
	- 使用建立好的合約
	
	```
	var regestryContract = web3.eth.contract([{"constant":true,"inputs":[{"name":"personaAddress","type":"address"}],"name":"getAttributes","outputs":[{"name":"","type":"bytes"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"version","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"previousPublishedVersion","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"ipfsHash","type":"bytes"}],"name":"setAttributes","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"ipfsAttributeLookup","outputs":[{"name":"","type":"bytes"}],"payable":false,"type":"function"},{"inputs":[{"name":"_previousPublishedVersion","type":"address"}],"type":"constructor","payable":true},{"anonymous":false,"inputs":[{"indexed":true,"name":"_sender","type":"address"},{"indexed":false,"name":"_timestamp","type":"uint256"}],"name":"AttributesSet","type":"event"}]);

	
	var registryAddress = '0x50D70fE5b00aD97b3Ab8389CA4EbE6BdC0320084';

	var registry = regestryContract.at(registryAddress)
	
	var attributes =
	{
	   "@context": "http://schema.org",
	   "@type": "Person",
	   "name": "Pinkman",
	   "image": [{"@type": "ImageObject",
	             "name": "avatar",
	             "contentUrl" : "/ipfs/QmUSBKeGYPmeHmLDAEHknAm5mFEvPhy2ekJc6sJwtrQ6nk"}]
	}
	
	
	var txHash = registry.setAttributes(attributes, {from: address, gas: '2000000'});
	console.log('txHash:', txHash);
	
	var regData = registry.getAttributes.call(address);
	console.log('regData', regData);
	
	// 要等transaction pended後,才可getAttibutes
	var regData = registry.getAttributes.call(proxy.address);

console.log('regData', regData); ``` - 使用uport-registry library(會寫到IPFS)

	```
	var uportRegistry = require("uport-registry");
	var ipfsApi = require('ipfs-api');

var web3 = require('web3'); uportRegistry.setIpfsProvider(ipfsApi(, ));

	uportRegistry.setWeb3Provider(new web3.providers.HttpProvider('http://localhost:8545'));
	var registryAddress = '0xbf014c4d7697cd83c9451a93648773cf510dc766'
	var attributes =
	{
	   "@context": "http://schema.org",
	   "@type": "Person",
	   "name": "Christian Lundkvist",
	   "image": [{"@type": "ImageObject",
	             "name": "avatar",
	             "contentUrl" : "/ipfs/QmUSBKeGYPmeHmLDAEHknAm5mFEvPhy2ekJc6sJwtrQ6nk"}]
	}
	uPortRegistry.setAttributes(
		registryAddress, 
		attributes, 
		{from: myAddr}).then(function ()
	     {console.log('Attributes set.')})
	                           
	```
  • uPort Proxy and Owner contracts
  • Owner contract with an User key that controls the proxy contract.
  • There is also an Admin key that can unilaterally replace the User key.
  • contracts
    • Proxy.sol
    • IdentityFactory.sol
    • Lib1.sol
    • MetaTxController.sol
    • Mirgration.sol
    • Owned.sol
    • Proxy.sol
    • RecoverableController.sol
    • RecoveryQuorum.sol
    • TestRegistry.sol
  • Deploy
    • Run truffle compile,會產生 build\contracts\ 目錄下的檔案

    • Run node deploy.js,會產生IdentityFactory Contract Address

    • CreateProxyWithControllerAndRecovery

      • address userKey: user key
      • address[] delegates: recovery keys
      • uint longTimeLock: long timelock
      • uint shortTimeLock: short timelock

identityFactory.CreateProxyWithControllerAndRecovery(userKey, delegates, longTimeLock, shortTimeLock, { from: address, gas: 2500000}); console.log('CreateProxyWithControllerAndRecovery created!!!!') ``` - Get related contract address

	```
	function getCreatedContractAddress() {
	  var event = identityFactory.IdentityCreated({creator: creatorAddress})
	  event.watch((error, result) => {
	    event.stopWatching();
	    proxyAddress = result.args.proxy;
	    controllerAddress = result.args.controller;
	    console.log("proxyAddress:", proxyAddress);
	    console.log("controllerAddress:", controllerAddress);
	  });
	}
	```
  • 測試
    • (1) 用TestRegistry Contract測試

      • address 需先unlock
         var lightwallet = require('eth-signer');
         function forwardTestRegistryFromController() {
         var LOG_NUMBER_1 = 12345678
         var data = lightwallet.txutils._encodeFunctionTxData('register', ['uint256'], [LOG_NUMBER_1]);
         data = '0x' + data;
         console.log('data:', data);
       
         // Example:
         var controllerParams = {from: address}
         var txHash = controller.forward(testReg.address, 0, data, controllerParams);
         var regData = testReg.registry.call(proxy.address);
         console.log('regData', regData);
       }
      
    • (2) 用Registry Contract 測試

       var lightwallet = require('eth-signer');
       function forwardRegistryFromController() {
         var attributes =
         {
            "@context": "http://schema.org",
            "@type": "Person",
            "name": "Amy Santiago",
            "image": [{"@type": "ImageObject",
                      "name": "avatar",
                      "contentUrl" : "/ipfs/QmUSBKeGYPmeHmLDAEHknAm5mFEvPhy2ekJc6sJwtrQ6nk"}]
         }
       
         var data = lightwallet.txutils._encodeFunctionTxData('setAttributes', ['bytes'], [attributes]);
         data = '0x' + data;
         console.log('data:', data);
       
         var controllerParams = {from: address, gas: '2000000'}
         var txHash = controller.forward(registry.address, 0, data, controllerParams);
         console.log('txHash:', txHash);
       
         var regData = registry.getAttributes.call(proxy.address);
         console.log('regData', regData);
      
       }
      
  • A library for creating, updating and reading attributes and claims on uport personas.

  • Importing Example

     import { Persona, MutablePersona } from 'uport-persona';
    
  • Query Persona

     // the address of the persona you want to interact with
     let myAddress = "0x123...";
     let ipfsProvider = {
       host: 'localhost',
       port: '5001',
       protocol: 'https',
       root: ''
     }
     let persona = new Persona(myAddress, ipfs, web3.currentProvider);
     persona.load().then(() => { ... });
    
  • UportProvider interface

  • dependent to uport-persona

  • 需搭配 messaging servermobile app 操作

  • RemoteMutablePersona

    • display QR code,由mobile app註冊/登入後,由 Chasqui (Messaging server)
  • UportSubprovider

    • options: msgServer, uportConnectHandler, ethUriHandler, closeQR
  • Importing example

     import Web3 from 'web3'
     import { Uport } from 'uport-lib'
     
     let web3 = new Web3()
     let options = {
       ipfsProvider: {
         host: '<IPFS_HOST>',
         port: '5001',
         protocol: 'https',
         root: ''
       }
     }
     let uport = new Uport('MyDApp', options)
     let rpcUrl = "http://<WEB3_HOST>:8545"
     let uportProvider = uport.getUportProvider(rpcUrl)
     
     web3.setProvider(uportProvider)
     
     uport.getUserPersona()
          .then((persona) => {
            let profile = persona.getProfile()
            console.log(profile)
          })
    
  • 其他未開源Componet

    • Mobile Application
    • Chasqui (Messaging server)
    • Sensui (Fueling server)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment