mirror of
https://github.com/Retropex/bitfeed.git
synced 2025-05-12 19:20:46 +02:00
Fix block download race condition
This commit is contained in:
parent
29627a5ebd
commit
1c2f9e5649
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "bitfeed-client",
|
"name": "bitfeed-client",
|
||||||
"version": "2.3.2",
|
"version": "2.3.3",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rollup -c",
|
"build": "rollup -c",
|
||||||
"dev": "rollup -c -w",
|
"dev": "rollup -c -w",
|
||||||
|
@ -3,7 +3,7 @@ import Overlay from '../components/Overlay.svelte'
|
|||||||
import Icon from './Icon.svelte'
|
import Icon from './Icon.svelte'
|
||||||
import BookmarkIcon from '../assets/icon/cil-bookmark.svg'
|
import BookmarkIcon from '../assets/icon/cil-bookmark.svg'
|
||||||
import { longBtcFormat, numberFormat, feeRateFormat, dateFormat } from '../utils/format.js'
|
import { longBtcFormat, numberFormat, feeRateFormat, dateFormat } from '../utils/format.js'
|
||||||
import { exchangeRates, settings, sidebarToggle, newHighlightQuery, highlightingFull, detailTx, pageWidth, latestBlockHeight, highlightInOut, loading, urlPath, currentBlock, overlay, explorerBlockData } from '../stores.js'
|
import { exchangeRates, settings, sidebarToggle, newHighlightQuery, highlightingFull, detailTx, pageWidth, latestBlockHeight, highlightInOut, loading, urlPath, currentBlock, overlay, explorerBlock } from '../stores.js'
|
||||||
import { formatCurrency } from '../utils/fx.js'
|
import { formatCurrency } from '../utils/fx.js'
|
||||||
import { hlToHex, mixColor, teal, purple } from '../utils/color.js'
|
import { hlToHex, mixColor, teal, purple } from '../utils/color.js'
|
||||||
import { SPKToAddress } from '../utils/encodings.js'
|
import { SPKToAddress } from '../utils/encodings.js'
|
||||||
@ -298,9 +298,11 @@ async function goToBlock(e) {
|
|||||||
let hash = $detailTx.block.hash || $detailTx.block.id
|
let hash = $detailTx.block.hash || $detailTx.block.id
|
||||||
let height = $detailTx.block.height
|
let height = $detailTx.block.height
|
||||||
if (hash === $currentBlock.id) {
|
if (hash === $currentBlock.id) {
|
||||||
|
onClose()
|
||||||
$overlay = null
|
$overlay = null
|
||||||
} else if (height == $latestBlockHeight) {
|
} else if (height == $latestBlockHeight) {
|
||||||
$explorerBlockData = null
|
onClose()
|
||||||
|
$explorerBlock = null
|
||||||
$overlay = null
|
$overlay = null
|
||||||
} else if (hash) {
|
} else if (hash) {
|
||||||
loading.increment()
|
loading.increment()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { urlPath, settings, loading, detailTx, highlightInOut, explorerBlockData, overlay } from '../stores.js'
|
import { urlPath, settings, loading, detailTx, highlightInOut, explorerBlock, overlay } from '../stores.js'
|
||||||
import { searchTx, searchBlockHash, searchBlockHeight } from '../utils/search.js'
|
import { searchTx, searchBlockHash, searchBlockHeight } from '../utils/search.js'
|
||||||
|
|
||||||
export default class Router {
|
export default class Router {
|
||||||
@ -37,7 +37,7 @@ export default class Router {
|
|||||||
detailTx.set(null)
|
detailTx.set(null)
|
||||||
highlightInOut.set(null)
|
highlightInOut.set(null)
|
||||||
urlPath.set("/")
|
urlPath.set("/")
|
||||||
explorerBlockData.set(null)
|
explorerBlock.set(null)
|
||||||
overlay.set(null)
|
overlay.set(null)
|
||||||
} else {
|
} else {
|
||||||
switch (parts[1]) {
|
switch (parts[1]) {
|
||||||
|
@ -6,7 +6,7 @@ import BitcoinBlock from '../models/BitcoinBlock.js'
|
|||||||
import TxSprite from '../models/TxSprite.js'
|
import TxSprite from '../models/TxSprite.js'
|
||||||
import { FastVertexArray } from '../utils/memory.js'
|
import { FastVertexArray } from '../utils/memory.js'
|
||||||
import { searchTx, fetchSpends, addSpends } from '../utils/search.js'
|
import { searchTx, fetchSpends, addSpends } from '../utils/search.js'
|
||||||
import { overlay, txCount, mempoolCount, mempoolScreenHeight, blockVisible, currentBlock, selectedTx, detailTx, blockAreaSize, highlight, colorMode, blocksEnabled, latestBlockHeight, explorerBlockData, blockTransitionDirection, loading, urlPath } from '../stores.js'
|
import { overlay, txCount, mempoolCount, mempoolScreenHeight, blockVisible, currentBlock, selectedTx, detailTx, blockAreaSize, highlight, colorMode, blocksEnabled, latestBlockHeight, explorerBlock, blockTransitionDirection, loading, urlPath } from '../stores.js'
|
||||||
import config from "../config.js"
|
import config from "../config.js"
|
||||||
import { tick } from 'svelte';
|
import { tick } from 'svelte';
|
||||||
|
|
||||||
@ -48,9 +48,9 @@ export default class TxController {
|
|||||||
colorMode.subscribe(mode => {
|
colorMode.subscribe(mode => {
|
||||||
this.setColorMode(mode)
|
this.setColorMode(mode)
|
||||||
})
|
})
|
||||||
explorerBlockData.subscribe(blockData => {
|
explorerBlock.subscribe(block => {
|
||||||
if (blockData) {
|
if (block) {
|
||||||
this.exploreBlock(blockData)
|
this.exploreBlock(block)
|
||||||
} else {
|
} else {
|
||||||
this.resumeLatest()
|
this.resumeLatest()
|
||||||
}
|
}
|
||||||
@ -168,21 +168,18 @@ export default class TxController {
|
|||||||
}).map(key => {
|
}).map(key => {
|
||||||
return {
|
return {
|
||||||
...this.txs[key],
|
...this.txs[key],
|
||||||
inputs: this.txs[key].inputs.map(input => { return {...input, script_pub_key: null, value: null }}),
|
inputs: this.txs[key].inputs ? this.txs[key].inputs.map(input => { return {...input, script_pub_key: null, value: null }}) : [],
|
||||||
}
|
}
|
||||||
})]
|
})]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
addBlock (blockData, realtime=true) {
|
addBlock (block, realtime=true) {
|
||||||
// discard duplicate blocks
|
// discard duplicate blocks
|
||||||
if (!blockData || !blockData.id || this.knownBlocks[blockData.id]) {
|
if (!block || !block.id || this.knownBlocks[block.id]) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let block
|
|
||||||
block = new BitcoinBlock(blockData)
|
|
||||||
|
|
||||||
latestBlockHeight.set(block.height)
|
latestBlockHeight.set(block.height)
|
||||||
// this.knownBlocks[block.id] = true
|
// this.knownBlocks[block.id] = true
|
||||||
if (this.clearBlockTimeout) clearTimeout(this.clearBlockTimeout)
|
if (this.clearBlockTimeout) clearTimeout(this.clearBlockTimeout)
|
||||||
@ -285,9 +282,7 @@ export default class TxController {
|
|||||||
return block
|
return block
|
||||||
}
|
}
|
||||||
|
|
||||||
async exploreBlock (blockData) {
|
async exploreBlock (block) {
|
||||||
const block = blockData.isBlock ? blockData : new BitcoinBlock(blockData)
|
|
||||||
|
|
||||||
if (this.block && this.block.id === block.id) {
|
if (this.block && this.block.id === block.id) {
|
||||||
this.showBlock()
|
this.showBlock()
|
||||||
return
|
return
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { serverConnected, serverDelay, lastBlockId } from '../stores.js'
|
import { serverConnected, serverDelay, lastBlockId, latestBlockHeight } from '../stores.js'
|
||||||
import config from '../config.js'
|
import config from '../config.js'
|
||||||
import api from '../utils/api.js'
|
import api from '../utils/api.js'
|
||||||
import { fetchBlockByHash } from '../utils/search.js'
|
import { fetchBlockByHash } from '../utils/search.js'
|
||||||
@ -6,7 +6,8 @@ import { fetchBlockByHash } from '../utils/search.js'
|
|||||||
let mempoolTimer
|
let mempoolTimer
|
||||||
let lastBlockSeen
|
let lastBlockSeen
|
||||||
lastBlockId.subscribe(val => { lastBlockSeen = val })
|
lastBlockId.subscribe(val => { lastBlockSeen = val })
|
||||||
|
let latestBlockHeightVal
|
||||||
|
latestBlockHeight.subscribe(val => { latestBlockHeightVal = val })
|
||||||
|
|
||||||
class TxStream {
|
class TxStream {
|
||||||
constructor () {
|
constructor () {
|
||||||
@ -122,8 +123,11 @@ class TxStream {
|
|||||||
async fetchBlock (id, calledOnLoad) {
|
async fetchBlock (id, calledOnLoad) {
|
||||||
if (!id) return
|
if (!id) return
|
||||||
if (id !== lastBlockSeen) {
|
if (id !== lastBlockSeen) {
|
||||||
const blockData = await fetchBlockByHash(id)
|
const block = await fetchBlockByHash(id)
|
||||||
window.dispatchEvent(new CustomEvent('bitcoin_block', { detail: { block: blockData, realtime: !calledOnLoad} }))
|
// ignore this block if we've downloaded a newer one while we were waiting
|
||||||
|
if (block.height >= latestBlockHeightVal) {
|
||||||
|
window.dispatchEvent(new CustomEvent('bitcoin_block', { detail: { block, realtime: !calledOnLoad} }))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log('already seen block ', lastBlockSeen)
|
console.log('already seen block ', lastBlockSeen)
|
||||||
}
|
}
|
||||||
|
@ -179,7 +179,7 @@ export const blocksEnabled = derived([settings], ([$settings]) => {
|
|||||||
export const latestBlockHeight = writable(null)
|
export const latestBlockHeight = writable(null)
|
||||||
export const highlightInOut = writable(null)
|
export const highlightInOut = writable(null)
|
||||||
export const loading = createCounter()
|
export const loading = createCounter()
|
||||||
export const explorerBlockData = writable(null)
|
export const explorerBlock = writable(null)
|
||||||
export const blockTransitionDirection = writable(null)
|
export const blockTransitionDirection = writable(null)
|
||||||
|
|
||||||
export const urlPath = writable(null)
|
export const urlPath = writable(null)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import api from './api.js'
|
import api from './api.js'
|
||||||
import BitcoinTx from '../models/BitcoinTx.js'
|
import BitcoinTx from '../models/BitcoinTx.js'
|
||||||
import BitcoinBlock from '../models/BitcoinBlock.js'
|
import BitcoinBlock from '../models/BitcoinBlock.js'
|
||||||
import { detailTx, selectedTx, currentBlock, explorerBlockData, overlay, highlightInOut, urlPath } from '../stores.js'
|
import { detailTx, selectedTx, currentBlock, explorerBlock, overlay, highlightInOut, urlPath } from '../stores.js'
|
||||||
import { addressToSPK } from './encodings.js'
|
import { addressToSPK } from './encodings.js'
|
||||||
|
|
||||||
// Quick heuristic matching to guess what kind of search a query is for
|
// Quick heuristic matching to guess what kind of search a query is for
|
||||||
@ -154,7 +154,7 @@ async function fetchBlockByHash (hash) {
|
|||||||
if (blockData) {
|
if (blockData) {
|
||||||
if (blockData.id) {
|
if (blockData.id) {
|
||||||
block = new BitcoinBlock(blockData)
|
block = new BitcoinBlock(blockData)
|
||||||
} else block = BitcoinBlock.decompress(blockData)
|
} else block = new BitcoinBlock(BitcoinBlock.decompress(blockData))
|
||||||
}
|
}
|
||||||
if (block && block.id) {
|
if (block && block.id) {
|
||||||
console.log('downloaded block', block.id)
|
console.log('downloaded block', block.id)
|
||||||
@ -255,7 +255,7 @@ export async function searchBlockHash (hash) {
|
|||||||
const searchResult = await fetchBlockByHash(hash)
|
const searchResult = await fetchBlockByHash(hash)
|
||||||
if (searchResult) {
|
if (searchResult) {
|
||||||
if (searchResult.id) {
|
if (searchResult.id) {
|
||||||
explorerBlockData.set(searchResult)
|
explorerBlock.set(searchResult)
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
} else {
|
} else {
|
||||||
@ -274,7 +274,7 @@ export async function searchBlockHeight (height) {
|
|||||||
const searchResult = await fetchBlockByHeight(height)
|
const searchResult = await fetchBlockByHeight(height)
|
||||||
if (searchResult) {
|
if (searchResult) {
|
||||||
if (searchResult.id) {
|
if (searchResult.id) {
|
||||||
explorerBlockData.set(searchResult)
|
explorerBlock.set(searchResult)
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
} else {
|
} else {
|
||||||
|
@ -4,7 +4,7 @@ defmodule BitcoinStream.MixProject do
|
|||||||
def project do
|
def project do
|
||||||
[
|
[
|
||||||
app: :bitcoin_stream,
|
app: :bitcoin_stream,
|
||||||
version: "2.3.2",
|
version: "2.3.3",
|
||||||
elixir: "~> 1.10",
|
elixir: "~> 1.10",
|
||||||
start_permanent: Mix.env() == :prod,
|
start_permanent: Mix.env() == :prod,
|
||||||
deps: deps(),
|
deps: deps(),
|
||||||
|
Loading…
Reference in New Issue
Block a user