mirror of
https://github.com/Permissionless-Software-Foundation/bch-js.git
synced 2026-09-21 16:51:59 -07:00
fix(utxo.get()): Detecting out-of-sync SLP indexer, protecting tokens
This commit is contained in:
+14
@@ -109,6 +109,11 @@ class UTXO {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the sync status of the SLP indexer
|
||||||
|
const syncStatus = await this.psfSlpIndexer.status()
|
||||||
|
const slpIndexerHeight = syncStatus.status.syncedBlockHeight
|
||||||
|
const chainBlockHeight = syncStatus.status.chainBlockHeight
|
||||||
|
|
||||||
// Loop through the Fulcrum UTXOs.
|
// Loop through the Fulcrum UTXOs.
|
||||||
for (let i = 0; i < utxos.length; i++) {
|
for (let i = 0; i < utxos.length; i++) {
|
||||||
const thisUtxo = utxos[i]
|
const thisUtxo = utxos[i]
|
||||||
@@ -152,6 +157,15 @@ class UTXO {
|
|||||||
thisUtxo.isSlp = false
|
thisUtxo.isSlp = false
|
||||||
}
|
}
|
||||||
// console.log(`thisUtxo.isSlp: ${thisUtxo.isSlp}`)
|
// console.log(`thisUtxo.isSlp: ${thisUtxo.isSlp}`)
|
||||||
|
|
||||||
|
// If the SLP indexer more than 1 block behind the full node, then
|
||||||
|
// move any BCH UTXOs of 600 sats or less into the null array. This
|
||||||
|
// protects token UTXOs from being burned accidentally.
|
||||||
|
if (slpIndexerHeight < chainBlockHeight - 1) {
|
||||||
|
if (thisUtxo.value < 601) {
|
||||||
|
thisUtxo.isSlp = null
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
This test is used to interrogate the behavior of bch-js when a psf-slp-indexer
|
||||||
|
panicks and starts indexing from SLP genesis. In this corner-case, bch-js
|
||||||
|
should detect the indexer is out of sync, and protect any token UTXOs by
|
||||||
|
moving any UTXO under 600 sats into the null array.
|
||||||
|
|
||||||
|
TO RUN THIS TEST:
|
||||||
|
- Reset a local instance of psf-slp-indexer to sync from genesis.
|
||||||
|
- Start a local copy of bch-api
|
||||||
|
*/
|
||||||
|
|
||||||
|
const BCHJS = require('../../../src/bch-js.js')
|
||||||
|
const bchjs = new BCHJS({
|
||||||
|
restURL: 'http://localhost:3000/v5/'
|
||||||
|
})
|
||||||
|
|
||||||
|
async function startTest () {
|
||||||
|
try {
|
||||||
|
const addr = 'bitcoincash:qzkvas58zag9tjry693mflkjze2m20ps7vx7uw7z9d'
|
||||||
|
|
||||||
|
const result = await bchjs.Utxo.get(addr)
|
||||||
|
console.log(`result: ${JSON.stringify(result, null, 2)}`)
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error in startTest(): ', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
startTest()
|
||||||
@@ -121,6 +121,8 @@ describe('#utxo', () => {
|
|||||||
sandbox
|
sandbox
|
||||||
.stub(bchjs.Utxo.psfSlpIndexer, 'tx')
|
.stub(bchjs.Utxo.psfSlpIndexer, 'tx')
|
||||||
.resolves({ txData: { isValidSlp: false } })
|
.resolves({ txData: { isValidSlp: false } })
|
||||||
|
sandbox.stub(bchjs.Utxo.psfSlpIndexer, 'status')
|
||||||
|
.resolves({ status: { syncedBlockHeight: 600000, chainBlockHeight: 600000 } })
|
||||||
|
|
||||||
// Mock function to return the same input. Good enough for this test.
|
// Mock function to return the same input. Good enough for this test.
|
||||||
sandbox.stub(bchjs.Utxo, 'hydrateTokenData').resolves(x => x)
|
sandbox.stub(bchjs.Utxo, 'hydrateTokenData').resolves(x => x)
|
||||||
@@ -154,6 +156,8 @@ describe('#utxo', () => {
|
|||||||
sandbox
|
sandbox
|
||||||
.stub(bchjs.Utxo.psfSlpIndexer, 'tx')
|
.stub(bchjs.Utxo.psfSlpIndexer, 'tx')
|
||||||
.resolves({ txData: { isValidSlp: false } })
|
.resolves({ txData: { isValidSlp: false } })
|
||||||
|
sandbox.stub(bchjs.Utxo.psfSlpIndexer, 'status')
|
||||||
|
.resolves({ status: { syncedBlockHeight: 600000, chainBlockHeight: 600000 } })
|
||||||
|
|
||||||
// Force psf-slp-indexer to return no UTXOs
|
// Force psf-slp-indexer to return no UTXOs
|
||||||
sandbox
|
sandbox
|
||||||
|
|||||||
Reference in New Issue
Block a user