DappCon, 20 July 2018
Tomasz Drwięga, @tomusdrw
A special kind of node that is, well, "light".
Sync Time
State Size
DB Size
Full Node
Light Node
~ days
~ seconds
~ gigs
0
~ tens of gigs
~ megs
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
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
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?
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
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.
// 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
You can compose the bonds
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
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
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
Tomasz Drwięga
@tomusdrw