mirror of
https://github.com/Permissionless-Software-Foundation/bch-js.git
synced 2026-09-21 16:51:59 -07:00
fix(tokenUtxoDetails): handling dust attack transactions better
This commit is contained in:
+1
-1
@@ -16,7 +16,7 @@
|
|||||||
"test:integration:free": "bash test/integration/test-free-tier.sh",
|
"test:integration:free": "bash test/integration/test-free-tier.sh",
|
||||||
"test:integration:free:bchn": "bash test/integration/test-free-tier-bchn.sh",
|
"test:integration:free:bchn": "bash test/integration/test-free-tier-bchn.sh",
|
||||||
"test:integration:free:testnet": "bash test/integration/testnet/test-free-tier.sh",
|
"test:integration:free:testnet": "bash test/integration/testnet/test-free-tier.sh",
|
||||||
"test:temp": "mocha --timeout 30000 -g '#blockHeader' test/unit/electrumx.js",
|
"test:temp": "mocha --timeout 30000 -g '#dustattack' test/unit/slp-utils.js",
|
||||||
"test:integration:api": "RESTURL=https://api.fullstack.cash/v3/ mocha --timeout 30000 test/integration",
|
"test:integration:api": "RESTURL=https://api.fullstack.cash/v3/ mocha --timeout 30000 test/integration",
|
||||||
"coverage": "nyc report --reporter=text-lcov | coveralls",
|
"coverage": "nyc report --reporter=text-lcov | coveralls",
|
||||||
"coverage:report": "nyc --reporter=html mocha --timeout 25000 test/unit/",
|
"coverage:report": "nyc --reporter=html mocha --timeout 25000 test/unit/",
|
||||||
|
|||||||
+11
-9
@@ -194,7 +194,7 @@ class Utils {
|
|||||||
path = `${this.restURL}slp/list`
|
path = `${this.restURL}slp/list`
|
||||||
}
|
}
|
||||||
|
|
||||||
//console.log(`path: ${path}`)
|
// console.log(`path: ${path}`)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let response
|
let response
|
||||||
@@ -316,7 +316,7 @@ class Utils {
|
|||||||
return response.data
|
return response.data
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(`Input address must be a string or array of strings.`)
|
throw new Error("Input address must be a string or array of strings.")
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.response && error.response.data) throw error.response.data
|
if (error.response && error.response.data) throw error.response.data
|
||||||
throw error
|
throw error
|
||||||
@@ -499,7 +499,7 @@ class Utils {
|
|||||||
typeof txid !== "string" ||
|
typeof txid !== "string" ||
|
||||||
txid.length !== 64
|
txid.length !== 64
|
||||||
)
|
)
|
||||||
throw new Error(`txid must be 64 character string.`)
|
throw new Error("txid must be 64 character string.")
|
||||||
|
|
||||||
const path = `${this.restURL}slp/validateTxid2/${txid}`
|
const path = `${this.restURL}slp/validateTxid2/${txid}`
|
||||||
|
|
||||||
@@ -700,7 +700,7 @@ class Utils {
|
|||||||
typeof txid !== "string" ||
|
typeof txid !== "string" ||
|
||||||
txid.length !== 64
|
txid.length !== 64
|
||||||
)
|
)
|
||||||
throw new Error(`txid string must be included.`)
|
throw new Error("txid string must be included.")
|
||||||
|
|
||||||
// console.log(`this.restURL: ${this.restURL}`)
|
// console.log(`this.restURL: ${this.restURL}`)
|
||||||
const path = `${this.restURL}slp/txDetails/${txid}`
|
const path = `${this.restURL}slp/txDetails/${txid}`
|
||||||
@@ -767,7 +767,8 @@ class Utils {
|
|||||||
// Then pass that cache object back into this function every time its called.
|
// Then pass that cache object back into this function every time its called.
|
||||||
if (cache) {
|
if (cache) {
|
||||||
if (!(cache instanceof Object))
|
if (!(cache instanceof Object))
|
||||||
throw new Error(`decodeOpReturn cache parameter must be Object`)
|
throw new Error("decodeOpReturn cache parameter must be Object")
|
||||||
|
|
||||||
const cachedVal = cache[txid]
|
const cachedVal = cache[txid]
|
||||||
if (cachedVal) return cachedVal
|
if (cachedVal) return cachedVal
|
||||||
}
|
}
|
||||||
@@ -775,7 +776,7 @@ class Utils {
|
|||||||
try {
|
try {
|
||||||
// Validate the txid input.
|
// Validate the txid input.
|
||||||
if (!txid || txid === "" || typeof txid !== "string")
|
if (!txid || txid === "" || typeof txid !== "string")
|
||||||
throw new Error(`txid string must be included.`)
|
throw new Error("txid string must be included.")
|
||||||
|
|
||||||
// Retrieve the transaction object from the full node.
|
// Retrieve the transaction object from the full node.
|
||||||
const path = `${this.restURL}rawtransactions/getRawTransaction/${txid}?verbose=true`
|
const path = `${this.restURL}rawtransactions/getRawTransaction/${txid}?verbose=true`
|
||||||
@@ -897,7 +898,7 @@ class Utils {
|
|||||||
const decodeOpReturnCache = {}
|
const decodeOpReturnCache = {}
|
||||||
const cachedTxValidation = {}
|
const cachedTxValidation = {}
|
||||||
// Throw error if input is not an array.
|
// Throw error if input is not an array.
|
||||||
if (!Array.isArray(utxos)) throw new Error(`Input must be an array.`)
|
if (!Array.isArray(utxos)) throw new Error("Input must be an array.")
|
||||||
|
|
||||||
// Loop through each element in the array and validate the input before
|
// Loop through each element in the array and validate the input before
|
||||||
// further processing.
|
// further processing.
|
||||||
@@ -963,7 +964,8 @@ class Utils {
|
|||||||
// to display the unknown state.
|
// to display the unknown state.
|
||||||
if (
|
if (
|
||||||
!err.message ||
|
!err.message ||
|
||||||
err.message.indexOf("scriptpubkey not op_return") === -1
|
(err.message.indexOf("scriptpubkey not op_return") === -1 &&
|
||||||
|
err.message.indexOf("lokad id") === -1)
|
||||||
) {
|
) {
|
||||||
// console.log(`error from decodeOpReturn(${utxo.txid}): `, err)
|
// console.log(`error from decodeOpReturn(${utxo.txid}): `, err)
|
||||||
|
|
||||||
@@ -1263,7 +1265,7 @@ class Utils {
|
|||||||
async hydrateUtxos(utxos) {
|
async hydrateUtxos(utxos) {
|
||||||
try {
|
try {
|
||||||
// Throw error if input is not an array.
|
// Throw error if input is not an array.
|
||||||
if (!Array.isArray(utxos)) throw new Error(`Input must be an array.`)
|
if (!Array.isArray(utxos)) throw new Error("Input must be an array.")
|
||||||
|
|
||||||
const response = await axios.post(
|
const response = await axios.post(
|
||||||
`${this.restURL}slp/hydrateUtxos`,
|
`${this.restURL}slp/hydrateUtxos`,
|
||||||
|
|||||||
@@ -437,6 +437,30 @@ describe(`#SLP`, () => {
|
|||||||
assert.equal(data[0].isValid, false)
|
assert.equal(data[0].isValid, false)
|
||||||
assert.equal(data[1].isValid, false)
|
assert.equal(data[1].isValid, false)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should handle a dust attack", async () => {
|
||||||
|
// it("#dustattack", async () => {
|
||||||
|
const utxos = [
|
||||||
|
{
|
||||||
|
height: 655965,
|
||||||
|
tx_hash:
|
||||||
|
"a675af87dcd8d39be782737aa52e0076b52eb2f5ce355ffcb5567a64dd96b77e",
|
||||||
|
tx_pos: 151,
|
||||||
|
value: 547,
|
||||||
|
satoshis: 547,
|
||||||
|
txid:
|
||||||
|
"a675af87dcd8d39be782737aa52e0076b52eb2f5ce355ffcb5567a64dd96b77e",
|
||||||
|
vout: 151,
|
||||||
|
address: "bitcoincash:qq4dw3sm8qvglspy6w2qg0u2ugsy9zcfcqrpeflwww",
|
||||||
|
hdIndex: 11
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const data = await bchjs.SLP.Utils.tokenUtxoDetails(utxos)
|
||||||
|
// console.log(`data: ${JSON.stringify(data, null, 2)}`)
|
||||||
|
|
||||||
|
assert.equal(data[0].isValid, false)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("#balancesForAddress", () => {
|
describe("#balancesForAddress", () => {
|
||||||
|
|||||||
@@ -1735,6 +1735,36 @@ describe("#SLP Utils", () => {
|
|||||||
assert.equal(data[0].isValid, null)
|
assert.equal(data[0].isValid, null)
|
||||||
assert.equal(data[1].isValid, null)
|
assert.equal(data[1].isValid, null)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// it("should handle a dust attack", async () => {
|
||||||
|
it("#dustattack", async () => {
|
||||||
|
// Mock external dependencies.
|
||||||
|
// Stub the calls to decodeOpReturn.
|
||||||
|
sandbox
|
||||||
|
.stub(slp.Utils, "decodeOpReturn")
|
||||||
|
.rejects(new Error("lokad id wrong size"))
|
||||||
|
|
||||||
|
const utxos = [
|
||||||
|
{
|
||||||
|
height: 655965,
|
||||||
|
tx_hash:
|
||||||
|
"a675af87dcd8d39be782737aa52e0076b52eb2f5ce355ffcb5567a64dd96b77e",
|
||||||
|
tx_pos: 151,
|
||||||
|
value: 547,
|
||||||
|
satoshis: 547,
|
||||||
|
txid:
|
||||||
|
"a675af87dcd8d39be782737aa52e0076b52eb2f5ce355ffcb5567a64dd96b77e",
|
||||||
|
vout: 151,
|
||||||
|
address: "bitcoincash:qq4dw3sm8qvglspy6w2qg0u2ugsy9zcfcqrpeflwww",
|
||||||
|
hdIndex: 11
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const data = await slp.Utils.tokenUtxoDetails(utxos)
|
||||||
|
// console.log(`data: ${JSON.stringify(data, null, 2)}`)
|
||||||
|
|
||||||
|
assert.equal(data[0].isValid, false)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("#txDetails", () => {
|
describe("#txDetails", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user