@bsv/sdk 1.1.22 → 1.1.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/src/compat/BSM.js +10 -3
- package/dist/cjs/src/compat/BSM.js.map +1 -1
- package/dist/cjs/src/primitives/Curve.js +7 -7
- package/dist/cjs/src/primitives/Curve.js.map +1 -1
- package/dist/cjs/src/primitives/ECDSA.js +394 -71
- package/dist/cjs/src/primitives/ECDSA.js.map +1 -1
- package/dist/cjs/src/primitives/Point.js +103 -23
- package/dist/cjs/src/primitives/Point.js.map +1 -1
- package/dist/cjs/src/primitives/TransactionSignature.js +4 -3
- package/dist/cjs/src/primitives/TransactionSignature.js.map +1 -1
- package/dist/cjs/src/primitives/utils.js +53 -16
- package/dist/cjs/src/primitives/utils.js.map +1 -1
- package/dist/cjs/src/script/Spend.js +6 -43
- package/dist/cjs/src/script/Spend.js.map +1 -1
- package/dist/cjs/src/script/templates/P2PKH.js +2 -2
- package/dist/cjs/src/script/templates/P2PKH.js.map +1 -1
- package/dist/cjs/src/script/templates/RPuzzle.js +2 -2
- package/dist/cjs/src/script/templates/RPuzzle.js.map +1 -1
- package/dist/cjs/src/transaction/Transaction.js +79 -65
- package/dist/cjs/src/transaction/Transaction.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/src/compat/BSM.js +10 -3
- package/dist/esm/src/compat/BSM.js.map +1 -1
- package/dist/esm/src/primitives/Curve.js +7 -7
- package/dist/esm/src/primitives/Curve.js.map +1 -1
- package/dist/esm/src/primitives/ECDSA.js +394 -71
- package/dist/esm/src/primitives/ECDSA.js.map +1 -1
- package/dist/esm/src/primitives/Point.js +103 -23
- package/dist/esm/src/primitives/Point.js.map +1 -1
- package/dist/esm/src/primitives/TransactionSignature.js +4 -3
- package/dist/esm/src/primitives/TransactionSignature.js.map +1 -1
- package/dist/esm/src/primitives/utils.js +51 -15
- package/dist/esm/src/primitives/utils.js.map +1 -1
- package/dist/esm/src/script/Spend.js +5 -42
- package/dist/esm/src/script/Spend.js.map +1 -1
- package/dist/esm/src/script/templates/P2PKH.js +2 -2
- package/dist/esm/src/script/templates/P2PKH.js.map +1 -1
- package/dist/esm/src/script/templates/RPuzzle.js +2 -2
- package/dist/esm/src/script/templates/RPuzzle.js.map +1 -1
- package/dist/esm/src/transaction/Transaction.js +79 -65
- package/dist/esm/src/transaction/Transaction.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/src/compat/BSM.d.ts +3 -2
- package/dist/types/src/compat/BSM.d.ts.map +1 -1
- package/dist/types/src/primitives/ECDSA.d.ts.map +1 -1
- package/dist/types/src/primitives/Point.d.ts +5 -0
- package/dist/types/src/primitives/Point.d.ts.map +1 -1
- package/dist/types/src/primitives/TransactionSignature.d.ts.map +1 -1
- package/dist/types/src/primitives/utils.d.ts +1 -0
- package/dist/types/src/primitives/utils.d.ts.map +1 -1
- package/dist/types/src/script/Spend.d.ts.map +1 -1
- package/dist/types/src/script/templates/P2PKH.d.ts +1 -1
- package/dist/types/src/script/templates/P2PKH.d.ts.map +1 -1
- package/dist/types/src/script/templates/RPuzzle.d.ts +1 -1
- package/dist/types/src/script/templates/RPuzzle.d.ts.map +1 -1
- package/dist/types/src/transaction/Transaction.d.ts.map +1 -1
- package/dist/types/src/transaction/TransactionInput.d.ts +1 -1
- package/dist/types/src/transaction/TransactionInput.d.ts.map +1 -1
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/docs/compat.md +10 -4
- package/docs/primitives.md +48 -12
- package/docs/script.md +4 -4
- package/docs/transaction.md +2 -1
- package/package.json +1 -1
- package/src/compat/BSM.ts +10 -3
- package/src/compat/__tests/BSM.test.ts +7 -2
- package/src/primitives/Curve.ts +7 -7
- package/src/primitives/ECDSA.ts +485 -75
- package/src/primitives/Point.ts +110 -25
- package/src/primitives/TransactionSignature.ts +4 -3
- package/src/primitives/utils.ts +58 -11
- package/src/script/Spend.ts +5 -48
- package/src/script/templates/P2PKH.ts +7 -7
- package/src/script/templates/RPuzzle.ts +8 -8
- package/src/transaction/Transaction.ts +93 -68
- package/src/transaction/TransactionInput.ts +1 -1
- package/src/transaction/__tests/Transaction.benchmarks.test.ts +222 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
// __tests__/transaction.benchmark.test.ts
|
|
2
|
+
|
|
3
|
+
import Transaction from '../../../dist/cjs/src/transaction/Transaction'
|
|
4
|
+
import PrivateKey from '../../../dist/cjs/src/primitives/PrivateKey'
|
|
5
|
+
import { hash160 } from '../../../dist/cjs/src/primitives/Hash'
|
|
6
|
+
import P2PKH from '../../../dist/cjs/src/script/templates/P2PKH'
|
|
7
|
+
import { jest } from '@jest/globals'
|
|
8
|
+
|
|
9
|
+
jest.setTimeout(60000) // Increase timeout for benchmarking tests if necessary
|
|
10
|
+
|
|
11
|
+
// Helper function to measure execution time
|
|
12
|
+
async function measureTime(fn: () => Promise<void>): Promise<number> {
|
|
13
|
+
const start = process.hrtime()
|
|
14
|
+
await fn()
|
|
15
|
+
const diff = process.hrtime(start)
|
|
16
|
+
const timeInMs = diff[0] * 1000 + diff[1] / 1e6
|
|
17
|
+
return timeInMs
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
describe('Transaction Verification Benchmark', () => {
|
|
21
|
+
const privateKey = new PrivateKey(1)
|
|
22
|
+
const publicKey = privateKey.toPublicKey()
|
|
23
|
+
const publicKeyHash = hash160(publicKey.toDER())
|
|
24
|
+
const p2pkh = new P2PKH()
|
|
25
|
+
|
|
26
|
+
it('verifies a transaction with a deep input chain', async () => {
|
|
27
|
+
// Create a deep chain of transactions (e.g., depth of 100)
|
|
28
|
+
const depth = 100
|
|
29
|
+
let tx = new Transaction()
|
|
30
|
+
tx.addOutput({
|
|
31
|
+
lockingScript: p2pkh.lock(publicKeyHash),
|
|
32
|
+
satoshis: 100000
|
|
33
|
+
})
|
|
34
|
+
tx.merklePath = {
|
|
35
|
+
// Mock merkle path verification
|
|
36
|
+
blockHeight: 0,
|
|
37
|
+
merkleRoot: '',
|
|
38
|
+
hashes: [],
|
|
39
|
+
verify: async () => true,
|
|
40
|
+
toBinary: () => [],
|
|
41
|
+
computeRoot: () => ''
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Build the chain
|
|
45
|
+
for (let i = 0; i < depth; i++) {
|
|
46
|
+
const newTx = new Transaction()
|
|
47
|
+
newTx.addInput({
|
|
48
|
+
sourceTransaction: tx,
|
|
49
|
+
sourceOutputIndex: 0,
|
|
50
|
+
unlockingScriptTemplate: p2pkh.unlock(privateKey),
|
|
51
|
+
sequence: 0xffffffff
|
|
52
|
+
})
|
|
53
|
+
newTx.addOutput({
|
|
54
|
+
lockingScript: p2pkh.lock(publicKeyHash),
|
|
55
|
+
satoshis: 100000 - 1000 * (i + 1)
|
|
56
|
+
})
|
|
57
|
+
await newTx.sign()
|
|
58
|
+
tx = newTx
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Measure verification time
|
|
62
|
+
const timeTaken = await measureTime(async () => {
|
|
63
|
+
const verified = await tx.verify('scripts only')
|
|
64
|
+
expect(verified).toBe(true)
|
|
65
|
+
})
|
|
66
|
+
console.log(`Verification time for deep chain of depth ${depth}: ${timeTaken.toFixed(2)} ms`)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('verifies a transaction with a wide input set', async () => {
|
|
70
|
+
// Create a transaction with many inputs (e.g., 100 inputs)
|
|
71
|
+
const inputCount = 100
|
|
72
|
+
const sourceTxs = []
|
|
73
|
+
|
|
74
|
+
// Create source transactions
|
|
75
|
+
for (let i = 0; i < inputCount; i++) {
|
|
76
|
+
const sourceTx = new Transaction()
|
|
77
|
+
sourceTx.addOutput({
|
|
78
|
+
lockingScript: p2pkh.lock(publicKeyHash),
|
|
79
|
+
satoshis: 1000
|
|
80
|
+
})
|
|
81
|
+
sourceTx.merklePath = {
|
|
82
|
+
blockHeight: 0,
|
|
83
|
+
merkleRoot: '',
|
|
84
|
+
hashes: [],
|
|
85
|
+
verify: async () => true,
|
|
86
|
+
toBinary: () => [],
|
|
87
|
+
computeRoot: () => ''
|
|
88
|
+
}
|
|
89
|
+
sourceTxs.push(sourceTx)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Create transaction with many inputs
|
|
93
|
+
const tx = new Transaction()
|
|
94
|
+
for (let i = 0; i < inputCount; i++) {
|
|
95
|
+
tx.addInput({
|
|
96
|
+
sourceTransaction: sourceTxs[i],
|
|
97
|
+
sourceOutputIndex: 0,
|
|
98
|
+
unlockingScriptTemplate: p2pkh.unlock(privateKey),
|
|
99
|
+
sequence: 0xffffffff
|
|
100
|
+
})
|
|
101
|
+
}
|
|
102
|
+
tx.addOutput({
|
|
103
|
+
lockingScript: p2pkh.lock(publicKeyHash),
|
|
104
|
+
satoshis: inputCount * 1000 - 1000
|
|
105
|
+
})
|
|
106
|
+
await tx.sign()
|
|
107
|
+
|
|
108
|
+
// Measure verification time
|
|
109
|
+
const timeTaken = await measureTime(async () => {
|
|
110
|
+
const verified = await tx.verify('scripts only')
|
|
111
|
+
expect(verified).toBe(true)
|
|
112
|
+
})
|
|
113
|
+
console.log(`Verification time for wide transaction with ${inputCount} inputs: ${timeTaken.toFixed(2)} ms`)
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
it('verifies a large transaction with many inputs and outputs', async () => {
|
|
117
|
+
const inputCount = 50
|
|
118
|
+
const outputCount = 50
|
|
119
|
+
const sourceTxs = []
|
|
120
|
+
|
|
121
|
+
// Create source transactions
|
|
122
|
+
for (let i = 0; i < inputCount; i++) {
|
|
123
|
+
const sourceTx = new Transaction()
|
|
124
|
+
sourceTx.addOutput({
|
|
125
|
+
lockingScript: p2pkh.lock(publicKeyHash),
|
|
126
|
+
satoshis: 2000
|
|
127
|
+
})
|
|
128
|
+
sourceTx.merklePath = {
|
|
129
|
+
blockHeight: 0,
|
|
130
|
+
merkleRoot: '',
|
|
131
|
+
hashes: [],
|
|
132
|
+
verify: async () => true,
|
|
133
|
+
toBinary: () => [],
|
|
134
|
+
computeRoot: () => ''
|
|
135
|
+
}
|
|
136
|
+
sourceTxs.push(sourceTx)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Create transaction with many inputs and outputs
|
|
140
|
+
const tx = new Transaction()
|
|
141
|
+
for (let i = 0; i < inputCount; i++) {
|
|
142
|
+
tx.addInput({
|
|
143
|
+
sourceTransaction: sourceTxs[i],
|
|
144
|
+
sourceOutputIndex: 0,
|
|
145
|
+
unlockingScriptTemplate: p2pkh.unlock(privateKey),
|
|
146
|
+
sequence: 0xffffffff
|
|
147
|
+
})
|
|
148
|
+
}
|
|
149
|
+
for (let i = 0; i < outputCount; i++) {
|
|
150
|
+
tx.addOutput({
|
|
151
|
+
lockingScript: p2pkh.lock(publicKeyHash),
|
|
152
|
+
satoshis: 1000
|
|
153
|
+
})
|
|
154
|
+
}
|
|
155
|
+
await tx.sign()
|
|
156
|
+
|
|
157
|
+
// Measure verification time
|
|
158
|
+
const timeTaken = await measureTime(async () => {
|
|
159
|
+
const verified = await tx.verify('scripts only')
|
|
160
|
+
expect(verified).toBe(true)
|
|
161
|
+
})
|
|
162
|
+
console.log(`Verification time for large transaction with ${inputCount} inputs and ${outputCount} outputs: ${timeTaken.toFixed(2)} ms`)
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
it('verifies a transaction with nested inputs (complex graph)', async () => {
|
|
166
|
+
// Create a transaction graph where inputs come from transactions with multiple inputs
|
|
167
|
+
const depth = 5
|
|
168
|
+
const fanOut = 3
|
|
169
|
+
let txs = []
|
|
170
|
+
|
|
171
|
+
// Create base transactions
|
|
172
|
+
for (let i = 0; i < fanOut; i++) {
|
|
173
|
+
const baseTx = new Transaction()
|
|
174
|
+
baseTx.addOutput({
|
|
175
|
+
lockingScript: p2pkh.lock(publicKeyHash),
|
|
176
|
+
satoshis: 100000
|
|
177
|
+
})
|
|
178
|
+
baseTx.merklePath = {
|
|
179
|
+
blockHeight: 0,
|
|
180
|
+
merkleRoot: '',
|
|
181
|
+
hashes: [],
|
|
182
|
+
verify: async () => true,
|
|
183
|
+
toBinary: () => [],
|
|
184
|
+
computeRoot: () => ''
|
|
185
|
+
}
|
|
186
|
+
txs.push(baseTx)
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Build the graph
|
|
190
|
+
for (let d = 0; d < depth; d++) {
|
|
191
|
+
const newTxs = []
|
|
192
|
+
for (const tx of txs) {
|
|
193
|
+
const newTx = new Transaction()
|
|
194
|
+
for (let i = 0; i < fanOut; i++) {
|
|
195
|
+
newTx.addInput({
|
|
196
|
+
sourceTransaction: tx,
|
|
197
|
+
sourceOutputIndex: 0,
|
|
198
|
+
unlockingScriptTemplate: p2pkh.unlock(privateKey),
|
|
199
|
+
sequence: 0xffffffff
|
|
200
|
+
})
|
|
201
|
+
}
|
|
202
|
+
newTx.addOutput({
|
|
203
|
+
lockingScript: p2pkh.lock(publicKeyHash),
|
|
204
|
+
satoshis: tx.outputs[0].satoshis - 1000 * fanOut
|
|
205
|
+
})
|
|
206
|
+
await newTx.sign()
|
|
207
|
+
newTxs.push(newTx)
|
|
208
|
+
}
|
|
209
|
+
txs = newTxs
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Take the last transaction for verification
|
|
213
|
+
const finalTx = txs[0]
|
|
214
|
+
|
|
215
|
+
// Measure verification time
|
|
216
|
+
const timeTaken = await measureTime(async () => {
|
|
217
|
+
const verified = await finalTx.verify('scripts only')
|
|
218
|
+
expect(verified).toBe(true)
|
|
219
|
+
})
|
|
220
|
+
console.log(`Verification time for nested inputs with depth ${depth} and fan-out ${fanOut}: ${timeTaken.toFixed(2)} ms`)
|
|
221
|
+
})
|
|
222
|
+
})
|