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?
- 701