Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 124 additions & 0 deletions test/lazy-proof-dependencies.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
const test = require('tape')
const { spawnSync } = require('node:child_process')
const path = require('node:path')

function runIsolated (t, source) {
const child = spawnSync(process.execPath, [
'--unhandled-rejections=strict', '-e', source, require.resolve('..')
], {
cwd: path.resolve(__dirname, '..'),
encoding: 'utf8',
timeout: 10000
})
t.error(child.error, 'isolated process completes')
t.equal(child.status, 0, child.stderr || 'isolated assertions pass')
t.end()
}

test('ordinary imports tolerate unavailable proof dependencies until proof use', t => {
runIsolated(t, `
const assert = require('node:assert/strict')
const Module = require('node:module')
const load = Module._load
const failure = new Error('proof dependency unavailable')
const requests = []
const proofPackages = new Set([
'eth-proof', 'eth-util-lite', 'eth-object',
'merkle-patricia-tree', 'ethereumjs-util', 'elliptic'
])
Module._load = function (request) {
if (proofPackages.has(request)) {
requests.push(request)
throw failure
}
return load.apply(this, arguments)
}
const library = require(process.argv[1])
assert.equal(typeof library.utils.HDSigner, 'function')
assert.equal(typeof library.utils.buildEthProof, 'function')
assert.equal(typeof library.SyscoinJSLib.prototype.assetAllocationMint, 'function')
assert.deepEqual(requests, [])
;(async () => {
await assert.rejects(library.utils.buildEthProof({}), error => error === failure)
assert.deepEqual(requests, ['eth-proof'])
})().catch(error => { console.error(error); process.exitCode = 1 })
`)
})

test('first proof use loads its dependencies and preserves constructor rejection', t => {
runIsolated(t, `
const assert = require('node:assert/strict')
const Module = require('node:module')
const load = Module._load
const requests = []
const failure = new Error('proof constructor failure')
const endpoint = 'http://127.0.0.1:1'
let constructions = 0
const replacements = {
'eth-proof': {
VerifyProof: {},
GetProof: class {
constructor (url) {
assert.equal(url, endpoint)
constructions++
throw failure
}
}
},
'eth-util-lite': { encode () {} },
'eth-object': { Log: {} }
}
Module._load = function (request) {
if (Object.hasOwn(replacements, request)) {
requests.push(request)
return replacements[request]
}
return load.apply(this, arguments)
}
const library = require(process.argv[1])
assert.deepEqual(requests, [])
;(async () => {
await assert.rejects(library.utils.buildEthProof({ web3url: endpoint }), error => error === failure)
assert.deepEqual(requests, ['eth-proof', 'eth-util-lite', 'eth-object'])
assert.equal(constructions, 1)
})().catch(error => { console.error(error); process.exitCode = 1 })
`)
})

test('proof execution failures retain the existing returned-error behavior', t => {
runIsolated(t, `
const assert = require('node:assert/strict')
const Module = require('node:module')
const load = Module._load
const failure = new Error('proof request failure')
const txid = '0x' + '11'.repeat(32)
let requests = 0
const replacements = {
'eth-proof': {
VerifyProof: {},
GetProof: class {
async transactionProof (hash) {
assert.equal(hash, txid)
requests++
throw failure
}
}
},
'eth-util-lite': { encode () {} },
'eth-object': { Log: {} }
}
Module._load = function (request) {
if (Object.hasOwn(replacements, request)) return replacements[request]
return load.apply(this, arguments)
}
const library = require(process.argv[1])
const messages = []
console.log = message => messages.push(message)
;(async () => {
const result = await library.utils.buildEthProof({ web3url: 'http://127.0.0.1:1', ethtxid: txid })
assert.equal(result, failure)
assert.equal(requests, 1)
assert.deepEqual(messages, ['Exception: proof request failure'])
})().catch(error => { console.error(error); process.exitCode = 1 })
`)
})
6 changes: 3 additions & 3 deletions utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ bjs.ECPair = ECPair
bjs.bip32 = bip32
const bitcoinops = require('bitcoin-ops')
const varuint = require('varuint-bitcoin')
const { VerifyProof, GetProof } = require('eth-proof')
const { encode } = require('eth-util-lite')
const { Log } = require('eth-object')
const { AbiCoder } = require('ethers/abi')
const { keccak256 } = require('ethers/crypto')
const { JsonRpcProvider } = require('ethers/providers')
Expand Down Expand Up @@ -1042,6 +1039,9 @@ Param assetOpts: Required. Object containing web3url and ethtxid fields populate
Returns: Returns JSON object in response, SPV proof object in JSON
*/
async function buildEthProof (assetOpts) {
const { VerifyProof, GetProof } = require('eth-proof')
const { encode } = require('eth-util-lite')
const { Log } = require('eth-object')
const ethProof = new GetProof(assetOpts.web3url)
const web3Provider = new JsonRpcProvider(assetOpts.web3url)
try {
Expand Down
Loading