Repository navigation
Expand file tree
/
Copy pathtest.js
More file actions
143 lines (139 loc) · 6.81 KB
/
Copy pathtest.js
File metadata and controls
143 lines (139 loc) · 6.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
'use strict'
const assert = {
equal (a, b) { if (a !== b) throw new Error('Values differ: ' + a + ' != ' + b) },
ok (value) { if (!value) throw new Error('Expected truthy value') },
match (value, pattern) { if (!pattern.test(value)) throw new Error('Pattern mismatch') },
deepEqual (a, b) { this.equal(JSON.stringify(a), JSON.stringify(b)) },
throws (fn, expected) {
let caught
try { fn() } catch (error) { caught = error }
if (!caught) throw new Error('Expected failure')
if (expected instanceof RegExp && !expected.test(caught.message)) throw caught
if (expected?.code && expected.code !== caught.code) throw caught
}
}
const fs = require('bare-fs')
const os = require('bare-os')
const path = require('bare-path')
const { NativeExternalSigner, SdkNode, getRuntimeInfo } = require('./index')
const expected = require('./runtime-contract.json')
const info = getRuntimeInfo()
assert.equal(info.rln_commit, expected.rln_commit)
assert.equal(info.adapter_sha256, expected.adapter_sha256)
assert.equal(info.wrapper_sha256, expected.wrapper_sha256)
assert.equal(info.lock_sha256, expected.lock_sha256)
assert.ok(info.capabilities.includes('persistent-native-signer'))
assert.ok(info.capabilities.includes('external-signer-burn-v1'))
require('./scripts/test-vss-safety-host')
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'rln-bare-release-canary-'))
const signerDir = path.join(root, 'signer')
const nodeDir = path.join(root, 'node')
let signer
let node
let bootstrap
try {
// Public deterministic fixture seed: this wallet must never be funded.
signer = NativeExternalSigner.createWithStorage('01'.repeat(32), 'regtest', signerDir)
bootstrap = signer.bootstrap()
assert.match(bootstrap.node_id, /^(02|03)[a-f0-9]{64}$/)
node = SdkNode.create({
storage_dir_path: nodeDir,
daemon_listening_port: 0,
ldk_peer_listening_port: 0,
network: 'regtest',
max_media_upload_size_mb: 5,
enable_virtual_channels_v0: false,
reuse_addresses: true
})
assert.throws(() => node.apayNewWithAddress('02'.repeat(33), 'canary', 'example.com'), /NotInitialized/)
assert.equal(typeof node.burn, 'function')
assert.equal(typeof node.burnAsset, 'function')
assert.throws(() => require('./binding').burn(node._handle, '{}'))
for (const method of ['syncWallet', 'walletSnapshot', 'prepareBtcSend', 'vssDeleteAll']) {
assert.throws(() => node[method]({}), { code: 'ERR_RLN_UNSUPPORTED_CAPABILITY' })
}
const raw = require('./binding')
for (const invalid of [undefined, null, {}, 1, 'node']) {
assert.throws(() => raw.nodeInfo(invalid))
assert.throws(() => raw.nativeExternalSignerShutdown(invalid))
assert.throws(() => raw.nativeExternalSignerDestroy(invalid))
}
assert.throws(() => raw.nodeInfo(signer._handle))
assert.throws(() => raw.nativeExternalSignerBootstrap(node._handle))
assert.throws(() => raw.nativeExternalSignerShutdown(node._handle))
assert.throws(() => raw.nativeExternalSignerDestroy(node._handle))
assert.throws(() => raw.sdkNodeDestroy(signer._handle))
assert.throws(() => raw.nativeExternalSignerNew('01'.repeat(32), 'regtest', 'false'))
assert.throws(() => raw.signMessage(node._handle, 42))
assert.throws(() => raw.signMessage(node._handle, 'bad\\0value'))
assert.throws(() => raw.btcBalance(node._handle, 0))
for (const value of [-1, 0, 65536, 1.5, NaN, Infinity, '1']) {
assert.throws(() => raw.estimateFee(node._handle, value))
}
node.initWithNativeExternalSigner(signer)
assert.throws(() => node.unlockWithNativeExternalSigner(signer, {}), /ldk_chain_sync/)
assert.throws(() => node.sendPayment({ invoice: 'unused', max_total_routing_fee_msat: 0 }), {
code: 'ERR_RLN_UNSUPPORTED_CAPABILITY'
})
node.shutdown()
node.shutdown()
node = undefined
signer.shutdown()
signer.shutdown()
assert.throws(() => signer.bootstrap(), /shut ?down|closed/i)
// The persistent store must reopen before the old host handle is freed.
const reopened = NativeExternalSigner.createWithStorage('01'.repeat(32), 'regtest', signerDir)
assert.deepEqual(reopened.bootstrap(), bootstrap)
signer.destroy()
signer.destroy()
assert.throws(() => signer.bootstrap(), /destroyed/)
signer = reopened
assert.deepEqual(signer.bootstrap(), bootstrap)
assert.equal(fs.statSync(signerDir).mode & 0o777, 0o700)
assert.throws(() => NativeExternalSigner.create('01'.repeat(32), 'mainnet', true))
} finally {
if (node) node.shutdown()
if (signer) { signer.shutdown(); signer.destroy() }
fs.rmSync(root, { recursive: true, force: true })
}
console.log('Native identity, offline init, errors, disposal and persistent signer reopen passed.')
const retainedRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'rln-bare-host-free-'))
let retainedNode
let retainedSigner
try {
const storage = path.join(retainedRoot, 'signer')
retainedSigner = NativeExternalSigner.createWithStorage('02'.repeat(32), 'regtest', storage)
const expectedBootstrap = retainedSigner.bootstrap()
retainedNode = SdkNode.create({ storage_dir_path: path.join(retainedRoot, 'node'),
daemon_listening_port: 0, ldk_peer_listening_port: 0, network: 'regtest',
max_media_upload_size_mb: 5, enable_virtual_channels_v0: false, reuse_addresses: true })
retainedNode.initWithNativeExternalSigner(retainedSigner)
retainedNode.attachNativeExternalSigner(retainedSigner)
retainedSigner.destroy()
// Freeing the host Arc must not revoke or release the still-attached signer.
assert.throws(() => NativeExternalSigner.createWithStorage('02'.repeat(32), 'regtest', storage),
/Database already open|Cannot acquire lock/)
retainedSigner = undefined
retainedNode.shutdown()
retainedNode = undefined
retainedSigner = NativeExternalSigner.createWithStorage('02'.repeat(32), 'regtest', storage)
assert.deepEqual(retainedSigner.bootstrap(), expectedBootstrap)
} finally {
if (retainedNode) retainedNode.shutdown()
if (retainedSigner) { retainedSigner.shutdown(); retainedSigner.destroy() }
fs.rmSync(retainedRoot, { recursive: true, force: true })
}
console.log('Early host-handle release preserves the attached signer until node shutdown.')
const mainnetRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'rln-mainnet-policy-'))
const mainnet = SdkNode.create({ storage_dir_path: mainnetRoot,
daemon_listening_port: 0, ldk_peer_listening_port: 0, network: 'mainnet',
max_media_upload_size_mb: 5, enable_virtual_channels_v0: false, reuse_addresses: true })
try {
assert.throws(() => mainnet.lnInvoice({ amt_msat: 1000, expiry_sec: 3600 }), /LightningUnsupportedOnMainnet/)
assert.throws(() => mainnet.listChannels(), /LightningUnsupportedOnMainnet/)
assert.throws(() => mainnet.btcBalance(true), /NotInitialized/)
} finally {
mainnet.shutdown()
fs.rmSync(mainnetRoot, { recursive: true, force: true })
}
console.log('Mainnet Lightning rejection and unchanged on-chain initialization requirements passed; no network connection or funds used.')