How to be Light Client friendly?

DappCon, 20 July 2018

Tomasz Drwięga, @tomusdrw

What is a Light Client?

A special kind of node that is, well, "light".

  • Low resource usage:
    CPU, Mem, Storage, IO
  • Embeddable
  • But still trustless

Why Light Clients?

Sync Time

State Size

DB Size

Full Node

Light Node

~ days

~ seconds

~ gigs

0

~ tens of gigs

~ megs

Parity Ethereum?

  • Deprecating the Parity Wallet (UI part)
  • Focusing on the Core Tech (full/light node)
  • Light Node + Light Wallet for casual users

How does it work?

Block 1

Block 2

Block 3

Transactions

Transactions

Transactions

(Header)

(Header)

(Header)

(Body)

(Body)

(Body)

State after 1

State after 2

State after 3

Full Node

How does it work?

Header 1

Header 2

Header 3

 

state_root

receipts_root

Light Node

 

state_root

receipts_root

 

state_root

receipts_root

We don't have the data, but we can verify it's validity if someone sends it

How development differs?

  • no pending block or pending transactions
  • actually no state at all
  • no block bodies (no transactions) nor receipts
  • network latency involved
  • some calls are more "expensive"

How to write a dapp?

const contract = web3.eth.Contract(
  ABI, "0x00..ff"
)

setInterval(async () => {
  const balance = await contract.methods
    .balanceOf("0x00..ff").call()
  
  document.querySelector('#balance')
    .textContent = balance
}, 500)

What if the node can't respond fast enough?

Smart Polling?

const contract = web3.eth.Contract(
  ABI, "0x00..ff"
)

async function updateBalance () {
  const balance = await contract.methods
    .balanceOf("0x00..ff").call()
  document.querySelector('#balance')
    .textContent = balance
}

const targetTime = 15 * 1000
setTimeout(function update () {
   const next = Date.now() + targetTime;
   updateBalance().then(() => {
    setTimeout(update, next - Date.now())
   })
})

Trying to target the block time and account for latency

Publish-Subscribe

const contract = web3.eth.Contract(
  ABI, "0x00..ff"
)

async function updateBalance () {
  const balance = await contract.methods
    .balanceOf("0x00..ff").call()
  document.querySelector('#balance')
    .textContent = balance
}

web3.eth
    .subscribe('newBlockHeaders')
    .on('data', updateBalance)

Only fetch when we know it might have changed.

Libraries
>
Patterns

oo7-parity

Bonds for Ethereum

// npm i oo7-parity
import {Bonds} from 'oo7-parity'

const bonds = Bonds(/* Optional Transport */)

// Process a stream of latest block numbers
bonds.blockNumber
    .map(b => `Current block: ${b}`)
    .tie(console.log) // Current block: 4512345
// npm i oo7-parity
import {Bonds, hexToAscii} from 'oo7-parity'

const bonds = Bonds()

// A bond for latest block extra data
bonds.blocks[bonds.blockNumber]
    .extraData
    .map(hexToAscii)
    .tie(console.log) // Parity.1.10

Bonds for Ethereum

You can compose the bonds

oo7

  • Computational graph (but JS is 1-thread)
  • "Simplified version of Observables"
  • JavaScript without typings
  • Insufficient documentation
  • "Magical" (Proxy object)

light.js

Rx.js for Ethereum

  • Reactive Extensions
  • Typescript
  • Minimal, high-level API
    (not yet another RPC wrapper)
  • Light Client friendly

light.js

import { blockNumber$ } from '@parity/light.js'
import { filter } from 'rxjs/operators'

blockNumber$()
  // Only log even blocks
  .pipe(filter(n => n % 2 === 0))
  .subscribe(console.log)

Observables

light.js

import { defaultAccount$, makeContract} 
  from '@parity/light.js'
import { switchMap }
  from 'rxjs/operators'

const contract = makeContract('0x00..ff', ABI)

defaultAccount$()
  .pipe(switchMap(
    account => contract.balanceOf$(account)
  ))
  .subscribe(console.log)

Calling Contracts

light.js

import light from '@parity/light.js-react'
import { syncing$ } from '@parity/light.js'

@light({
  syncStatus: syncing$
})
class MyClass extends React.Component {
  render() {
    return (
      <div>
        {JSON.stringify(this.props.syncStatus)}
      </div>
    )
  }
}

React Integration

light.js

  • Quite minimal currently
  • Still working on the API
  • Contributions welcome!

The Future?

  • More APIs in light.js
  • UI components libraries
  • Parity Ethereum as a library
    (Android / iOS)
  • Parity Ethereum as WASM
    (Light node on a website)

Thank you

Tomasz Drwięga
@tomusdrw

How to be Light Client friendly?

By Tomasz Drwięga

How to be Light Client friendly?

  • 688