@bsv/wallet-toolbox 1.6.38 → 1.6.40
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/CHANGELOG.md +8 -0
- package/mobile/out/src/sdk/WalletError.d.ts.map +1 -1
- package/mobile/out/src/sdk/WalletError.js +14 -5
- package/mobile/out/src/sdk/WalletError.js.map +1 -1
- package/mobile/out/src/services/chaintracker/chaintracks/Chaintracks.js +1 -1
- package/mobile/out/src/services/chaintracker/chaintracks/Chaintracks.js.map +1 -1
- package/mobile/out/src/storage/WalletStorageManager.d.ts +15 -4
- package/mobile/out/src/storage/WalletStorageManager.d.ts.map +1 -1
- package/mobile/out/src/storage/WalletStorageManager.js +29 -19
- package/mobile/out/src/storage/WalletStorageManager.js.map +1 -1
- package/mobile/out/src/storage/methods/createAction.d.ts.map +1 -1
- package/mobile/out/src/storage/methods/createAction.js +1 -1
- package/mobile/out/src/storage/methods/createAction.js.map +1 -1
- package/mobile/package-lock.json +2 -2
- package/mobile/package.json +1 -1
- package/out/src/sdk/WalletError.d.ts.map +1 -1
- package/out/src/sdk/WalletError.js +14 -5
- package/out/src/sdk/WalletError.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Chaintracks.js +1 -1
- package/out/src/services/chaintracker/chaintracks/Chaintracks.js.map +1 -1
- package/out/src/storage/WalletStorageManager.d.ts +15 -4
- package/out/src/storage/WalletStorageManager.d.ts.map +1 -1
- package/out/src/storage/WalletStorageManager.js +29 -19
- package/out/src/storage/WalletStorageManager.js.map +1 -1
- package/out/src/storage/methods/createAction.d.ts.map +1 -1
- package/out/src/storage/methods/createAction.js +1 -1
- package/out/src/storage/methods/createAction.js.map +1 -1
- package/out/test/Wallet/support/operations.man.test.js +10 -1
- package/out/test/Wallet/support/operations.man.test.js.map +1 -1
- package/out/tsconfig.all.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/sdk/WalletError.ts +13 -5
- package/src/services/chaintracker/chaintracks/Chaintracks.ts +1 -1
- package/src/storage/WalletStorageManager.ts +38 -20
- package/src/storage/methods/createAction.ts +2 -3
- package/test/Wallet/support/operations.man.test.ts +11 -1
package/package.json
CHANGED
package/src/sdk/WalletError.ts
CHANGED
|
@@ -147,14 +147,22 @@ export class WalletError extends Error implements WalletErrorObject {
|
|
|
147
147
|
static unknownToJson(error: unknown | WalletError): string {
|
|
148
148
|
let json: string | undefined
|
|
149
149
|
let e: WalletError | undefined
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
150
|
+
const t = typeof error
|
|
151
|
+
const ctor = t === 'object' && error !== null ? (error as any).constructor?.name : undefined
|
|
152
|
+
const name = t === 'object' && error !== null && typeof (error as any).name === 'string' ? (error as any).name : ''
|
|
153
|
+
const message = t === 'object' && error !== null && typeof (error as any).message === 'string' ? (error as any).message : ''
|
|
154
|
+
const toJson = t === 'object' && error !== null && typeof (error as any).toJson === 'function' ? (error as any).toJson : undefined
|
|
155
|
+
console.log(`WalletError.unknownToJson: error type=${t} ctor=${ctor} name=${name} message=${message} hasToJson=${toJson ? 'yes' : 'no'}`)
|
|
156
|
+
if (ctor && ctor.startsWith('WERR_') && toJson !== undefined) {
|
|
157
|
+
json = (error as WalletError).toJson()
|
|
158
|
+
} else if (name && message) {
|
|
159
|
+
e = new WalletError(name, message)
|
|
160
|
+
json = e.toJson()
|
|
154
161
|
} else {
|
|
155
162
|
e = new WalletError('WERR_UNKNOWN', String(error))
|
|
163
|
+
json = e.toJson()
|
|
156
164
|
}
|
|
157
|
-
|
|
165
|
+
console.log(`WalletError.unknownToJson: json=${json}`)
|
|
158
166
|
return json
|
|
159
167
|
}
|
|
160
168
|
}
|
|
@@ -462,7 +462,7 @@ export class Chaintracks implements ChaintracksManagementApi {
|
|
|
462
462
|
let skipBulkSync =
|
|
463
463
|
!before.live.isEmpty && before.live.maxHeight >= presentHeight - this.addLiveRecursionLimit / 2
|
|
464
464
|
|
|
465
|
-
if (skipBulkSync && now -
|
|
465
|
+
if (skipBulkSync && now - lastBulkSync > cdnSyncRepeatMsecs) {
|
|
466
466
|
// If we haven't re-synced in a long time, do it just to check for a CDN update.
|
|
467
467
|
skipBulkSync = false
|
|
468
468
|
}
|
|
@@ -565,50 +565,62 @@ export class WalletStorageManager implements sdk.WalletStorage {
|
|
|
565
565
|
}
|
|
566
566
|
|
|
567
567
|
/**
|
|
568
|
-
* Extends the Beef `verify` function to handle BUMPs that have become invalid due to a chain reorg
|
|
569
|
-
*
|
|
568
|
+
* Extends the Beef `verify` function to handle BUMPs that have become invalid due to a chain reorg,
|
|
569
|
+
* and originated from proven_txs records tracked by this storage.
|
|
570
|
+
*
|
|
571
|
+
* This method is optimized for making sure outgoing beefs are valid before sharing them externally.
|
|
572
|
+
* In particular, it only "repairs" proofs previously tracked by this storage.
|
|
573
|
+
*
|
|
570
574
|
* Any merkle root that fails `isValidRootForHeight` triggers a reprove attempt for that block header.
|
|
571
575
|
* This results in proven_txs with invalid proofs being updated with new valid proofs where possible.
|
|
572
|
-
* Finally, a new beef is generated and verified against the chaintracker.
|
|
573
576
|
*
|
|
574
577
|
* @param beef
|
|
575
578
|
* @param allowTxidOnly
|
|
576
|
-
* @returns
|
|
579
|
+
* @returns VerifyAndRepairBeefResult, in particular `verifiedBeef` is valid only verify and repair succeeded fully.
|
|
577
580
|
*/
|
|
578
|
-
async verifyAndRepairBeef(beef: Beef, allowTxidOnly?: boolean): Promise<
|
|
581
|
+
async verifyAndRepairBeef(beef: Beef, allowTxidOnly?: boolean): Promise<VerifyAndRepairBeefResult> {
|
|
579
582
|
throw new sdk.WERR_NOT_IMPLEMENTED()
|
|
580
583
|
|
|
584
|
+
const r: VerifyAndRepairBeefResult = {
|
|
585
|
+
isStructurallyValid: false,
|
|
586
|
+
originalRoots: {},
|
|
587
|
+
invalidRoots: {}
|
|
588
|
+
}
|
|
581
589
|
const services = this.getServices()
|
|
582
590
|
const chaintracker = await services.getChainTracker()
|
|
583
|
-
const verified = await beef.verify(chaintracker)
|
|
584
591
|
|
|
585
|
-
|
|
586
|
-
if (!r.valid) return false
|
|
592
|
+
;({ valid: r.isStructurallyValid, roots: r.originalRoots } = beef.verifyValid(allowTxidOnly))
|
|
587
593
|
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
594
|
+
if (!r.isStructurallyValid) return r
|
|
595
|
+
|
|
596
|
+
for (const [heightStr, root] of Object.entries(r.originalRoots)) {
|
|
597
|
+
const height = Number(heightStr)
|
|
598
|
+
const isValid = await chaintracker.isValidRootForHeight(root, height)
|
|
591
599
|
if (!isValid) {
|
|
592
|
-
|
|
600
|
+
// root is not currently the valid hash for this height according to the chaintracker.
|
|
601
|
+
// What beef txids depended on this root:
|
|
602
|
+
const txids = beef.txs.filter(tx => tx.bumpIndex !== undefined && beef.bumps[tx.bumpIndex].blockHeight === height).map(tx => tx.txid)
|
|
603
|
+
const reproveResults = await this.reproveHeader(root)
|
|
604
|
+
r.invalidRoots[height] = { root, reproveResults }
|
|
593
605
|
}
|
|
594
606
|
}
|
|
595
607
|
|
|
596
|
-
if (Object.keys(invalidRoots).length === 0) {
|
|
597
|
-
// There are no invalid merkle roots and the beef is structurally valid
|
|
598
|
-
//
|
|
599
|
-
return
|
|
608
|
+
if (Object.keys(r.invalidRoots).length === 0) {
|
|
609
|
+
// There are no invalid merkle roots and the beef is structurally valid.
|
|
610
|
+
// The beef is fully verified.
|
|
611
|
+
return r
|
|
600
612
|
}
|
|
601
613
|
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
const r = await this.reproveHeader(hash)
|
|
605
|
-
}
|
|
614
|
+
// beef is structurally valid but has invalid merkle roots.
|
|
615
|
+
// Attempt to repair the invalid roots by reproving all txids in this beef that relied on them.
|
|
606
616
|
|
|
607
617
|
// All invalid BUMPs must be removed from the beef
|
|
608
618
|
// and all txid's that were proven by those BUMPs need
|
|
609
619
|
// new beefs merged into the beef.
|
|
610
620
|
// In most cases, this will be a replacement BUMP,
|
|
611
621
|
// but it may also require a deeper proof.
|
|
622
|
+
|
|
623
|
+
return r
|
|
612
624
|
}
|
|
613
625
|
|
|
614
626
|
/**
|
|
@@ -922,3 +934,9 @@ export class WalletStorageManager implements sdk.WalletStorage {
|
|
|
922
934
|
return stores
|
|
923
935
|
}
|
|
924
936
|
}
|
|
937
|
+
|
|
938
|
+
export interface VerifyAndRepairBeefResult {
|
|
939
|
+
isStructurallyValid: boolean
|
|
940
|
+
originalRoots: Record<number, string>
|
|
941
|
+
invalidRoots: Record<number, { root: string, reproveResults: sdk.ReproveHeaderResult }>
|
|
942
|
+
}
|
|
@@ -10,8 +10,7 @@ import {
|
|
|
10
10
|
Random,
|
|
11
11
|
ReviewActionResult,
|
|
12
12
|
Script,
|
|
13
|
-
Utils
|
|
14
|
-
WERR_REVIEW_ACTIONS
|
|
13
|
+
Utils
|
|
15
14
|
} from '@bsv/sdk'
|
|
16
15
|
import {
|
|
17
16
|
generateChangeSdk,
|
|
@@ -35,7 +34,7 @@ import {
|
|
|
35
34
|
ValidCreateActionOutput,
|
|
36
35
|
validateSatoshis
|
|
37
36
|
} from '../../sdk/validationHelpers'
|
|
38
|
-
import { WERR_INTERNAL, WERR_INVALID_PARAMETER } from '../../sdk/WERR_errors'
|
|
37
|
+
import { WERR_INTERNAL, WERR_INVALID_PARAMETER, WERR_REVIEW_ACTIONS } from '../../sdk/WERR_errors'
|
|
39
38
|
import {
|
|
40
39
|
randomBytesBase64,
|
|
41
40
|
sha256Hash,
|
|
@@ -11,7 +11,7 @@ describe('operations.man tests', () => {
|
|
|
11
11
|
|
|
12
12
|
test('0 review and release all production invalid change utxos', async () => {
|
|
13
13
|
const { env, storage } = await _tu.createMainReviewSetup()
|
|
14
|
-
const users = await storage.findUsers({ partial: {} })
|
|
14
|
+
const users = await storage.findUsers({ partial: { userId: 124 } })
|
|
15
15
|
const withInvalid: Record<number, { user: TableUser; outputs: WalletOutput[]; total: number }> = {}
|
|
16
16
|
const vargs: ValidListOutputsArgs = {
|
|
17
17
|
basket: specOpInvalidChange,
|
|
@@ -326,6 +326,16 @@ describe('operations.man tests', () => {
|
|
|
326
326
|
logger(log)
|
|
327
327
|
await storage.destroy()
|
|
328
328
|
})
|
|
329
|
+
|
|
330
|
+
test('15 abort a transaction', async () => {
|
|
331
|
+
const { env, storage } = await _tu.createMainReviewSetup()
|
|
332
|
+
const refOrTxid = '42671b6c9b79cec03bf5be9105203589b8b092774a40b459fbd835e5fd582202'
|
|
333
|
+
const userId = 496
|
|
334
|
+
const auth = { userId, identityKey: '' }
|
|
335
|
+
const r = await storage.abortAction(auth, { reference: refOrTxid })
|
|
336
|
+
console.log(r)
|
|
337
|
+
await storage.destroy()
|
|
338
|
+
})
|
|
329
339
|
})
|
|
330
340
|
|
|
331
341
|
const testTxInputUtxoStatus = `010000003E63EAF142160AD52F3172D75305D0D495A99AD9F17A693017EF8630C86F37A200000000006A473044022004E94D9188B2CE1193969509F32B46F94A36DB2BB4FC0832936F937C59FDDA470220781E5A5AD34EE49C985E5177380D6D111546D7BCCBAAA219B292FB49400DB7C9C221021A67430A3C5F274D3563892965758D3DEAE67799DD47E28DA95FBD1013D3B302FFFFFFFF74B95869A62F82E50642B4B18C78321BC12858A640155C8DA34EC4043393CCA6000000006A4730440220680AEF159D6C158C703912A9FBA090A063A26D92DBDFB7F15D6026FB5EAC332E0220375559499733A35955CA5F562669C8A947624BF22A8475EC0CD2C488530BCBD1C22103F55B1909BFD6851773E7FA7E567B58BF586D1EF76D0DE00330EE7F05E19672C2FFFFFFFFCDA6E22336EA4F8898D56C85C022F35338A6CD9E8D14FC75EA39DEC3B78FB83E010000006B483045022100E2B532D81252E60465E694F40A67B8CC52CCEAA1992494AAE264E039ED4D471602204E5C65F74BB49D263C54E43CFE22C8AB39B8AEB89F64CFEF933E5EBE08C5EF6DC22103E4F28DF126FBE92CF4418EF16636D18D75F8FFEADF0D03A0339A53B4A37DDDF7FFFFFFFFE330B3BBCB5815DD6B2B03BA5105F71F09CB8C26344F67C7A5E082473DF75859030000006B483045022100EBF506D10F04EC171C6A598056F06946D0B6F244FD08AA3E5A2DABB2EAC01A2A02206E557D4D7048E19F1DE094C5BCB7FC507FEC7E13C419AE829AD9180BACE4D5D8C22102960CADC2656A19DAAF1FCC04F6CF235C0E83822336F3CD32D599A426DFF85114FFFFFFFF7A58F2A977D75EDC8D349AEC609DAEC3AB06C12CE83276FB986D0B36D37C3C3C090000006A47304402205B353BE3BBC19B3766D12D5268E34E34675EB8BB8DD7624A522C1A36C1A1F481022072DD8D7F11C5507781FE9C55931A95BB3FE0FF7748DB4D1765FB6DFCBDF27268C22103F051F897874F7365DBF96773EE4D54EEA289BF05EE1610FF8C7F52EBC15A8294FFFFFFFF2D1C1B9098484F91435CB9965F07886E30FB8D1EA7F221C9072DAD8AAD545B294C0000006A47304402205D42AC6A4CA02F7006781515E9DAB1101B2F8006193F7E3EEB61CDC3132EFDDE02203EB616AD39280D1A07E9B31D1E4BAF56F831AF95A21A16D304235DD7DC65CF20C22103F051F897874F7365DBF96773EE4D54EEA289BF05EE1610FF8C7F52EBC15A8294FFFFFFFF2D1C1B9098484F91435CB9965F07886E30FB8D1EA7F221C9072DAD8AAD545B29160000006B48304502210080AE055C991A3EFED069C3E0D22E984DAF0C2DDDE6C102280EAA6E7ABBA2E9A00220339DE057226FAD63D021A3167C3AEDA0447D49DFA782A59850F699012C44FA4DC221033F8A1AD07E37C12FCE914102509C9ABFC313F69D9329F5137FD2EA79F633C86CFFFFFFFFFBD56D01AAB9E6F7E73F0D6A232F4D73D552A933E3ECBFC2E4BD95F4ECF9A1C6020000006A473044022043AEAFBF8C63FC98CECFE79569BE2F0D94C02E44C2C50CAD37104C4EA0D0B8E4022072EA0F50DF429D15500F4F2795147256A40DEA751BECD6572E0C5AE51D6DF553C221033F8A1AD07E37C12FCE914102509C9ABFC313F69D9329F5137FD2EA79F633C86CFFFFFFFF1D6A18F2411362A374CE97D2480C54E21173A58C5E83D7679DB1BC5CA112A55D020000006A47304402204B5E9B9612F89CADC7BF2D7035BFFB1EE9127586F504D4C635B674D8A1BE000702207837EEC18E2BD808F58935C4C78685715B2C5A3D84AB39895F8DA1AA0F7E6A28C22102D7EAA52A92B311A96A0AEBB18CABFE3A9B17B82048ED1E3E58628A4959ED91B4FFFFFFFF4A2297374C26D0E5EE98C07FDA64DAD58577F89502835CD433EEC3191A66F380B30000006B483045022100CF83B0C64FD8ECA6761CC7BD3D72F2B38CC17B747C1E98F48DACD155B7CE9B3502202C696010E7673325CAEAE2E0D7F0BA8DC2EADC6FDB7A3779AA359820A16CD848C22102D7EAA52A92B311A96A0AEBB18CABFE3A9B17B82048ED1E3E58628A4959ED91B4FFFFFFFF589F60C44908602772131C5D457186E18F4D22D659353AC84F3A0795057F2378000000006B483045022100C4EC4D00EA39C2EBBA147752C67BB722B695777F00C462B7AE3E76467DB5EE9B02205402285B07031D4EA0FCCD298FED76F590243D1D9CE8B8C44F83F97B59691E9BC22103125E0DF790EAE42BFF3B6057A2699C534B3E4D08C1D3AFEC2AF4C10CC751EFD8FFFFFFFFB750A581EEA3A60079DE6D28FE07BAE3C7A63065D92DA936C67FE4C52F1C1DE6000000006A47304402201860470374A282FF58B6EE576A1EF46B60238131FD00D0C0C27777F8F76CAC4502204163110A54EB0B81C6F0791E363F3DF0F0A14C08F6A7AE2E8FC77B7713ED109BC22103125E0DF790EAE42BFF3B6057A2699C534B3E4D08C1D3AFEC2AF4C10CC751EFD8FFFFFFFF833F3725A47C30A4AD5EBE5EA46D9AED81D5213BA2B51DE74A8BF23B65AC99A39F0000006B483045022100F1B40B6D4053E817FC674872DB1B8FE8C64D625CF4974893846A490117D034C60220343365C584D60269BF7845AFD2B69B4CF230530091102B1493B32D7B73E0CA0FC22103125E0DF790EAE42BFF3B6057A2699C534B3E4D08C1D3AFEC2AF4C10CC751EFD8FFFFFFFF833F3725A47C30A4AD5EBE5EA46D9AED81D5213BA2B51DE74A8BF23B65AC99A39E0000006B483045022100A21CBDF75C58FAD76313F2CBE8D0E0DC1E3B5FCB9ECC61594A91D4F61218C85902202BB2250C3477EFC9D7C28F1D1E0ADB3296952671D340065ADA8B93A330C39244C22103584150A15E4D85DF54CFBBD822ACA5EEDE00D5DD8C32126FCBD51499519BA565FFFFFFFFA1DD547EAB22B19A49862C2ED7C3E059DBBB5307738F9D9581CED2B4AAB6B6D9010000006B483045022100A0918681C651851B91617C8E1C01074F2A0291EBB083AB2163D72FF565DD8590022008E27FC437A0DE19A3F39F3C2C3F1B3C1F508E52DC69ACC2CBF9D1774C7C4047C22103125E0DF790EAE42BFF3B6057A2699C534B3E4D08C1D3AFEC2AF4C10CC751EFD8FFFFFFFF0BB9D0E3A9CCEA73BC8682B66C559D6232265488647F0B7EEECE00BD0C2F5904000000006B483045022100C568678B624F6F04E8645AD8340638075E07AD4BCBB0FA9446B2153599B803C902204B9BD26BD58614360B86F95E9812E68A759450E64659AA5B8707FA629D12B438C22103125E0DF790EAE42BFF3B6057A2699C534B3E4D08C1D3AFEC2AF4C10CC751EFD8FFFFFFFF5367F929C9123A4853ED77A0087F72D135031A8E64C3D047976EFCD3807FC0D5010000006A47304402200B1F4939A427C65ED456B62158271F269C33740C5E4D9ED2F9E864E410F23511022059F10A7FEFE82CF89C274FE9486CFAEF7B148290386DDD3F6423280F0667EEF7C22103584150A15E4D85DF54CFBBD822ACA5EEDE00D5DD8C32126FCBD51499519BA565FFFFFFFF5367F929C9123A4853ED77A0087F72D135031A8E64C3D047976EFCD3807FC0D5000000006A473044022012D66417842DDF0079734B3885CE56D42B2309A49CFD1313895CE6401E67E47602200F8FCCBECEEC0546577872F4BA7B95EAF4621506238D88E89A0A0B12E46876DCC22103584150A15E4D85DF54CFBBD822ACA5EEDE00D5DD8C32126FCBD51499519BA565FFFFFFFF46CF567BCF79C0E845BC95A488DC8BEB8E3558783F21B30A2902F333D6080C3A000000006A47304402202DEBF679DE7F93DDABC84CC1953DC52570EF291F4BFE1C61840AAA2D3CDA0AF5022041C66B14238FE4CD4C5E7E3BF6BA2BDA031F7D4EACA3F15FC28DD6CDAF2B2E54C221036D9E146EDA0C9E01DF36F4735C39B29E8C8B58BFDB2BCF82E407A1CEEB8ED040FFFFFFFFA11701B6BC31DA3646DBAEBD0042AD7357B14A35B97461E9F2278DEB90FD6838D40000006A4730440220154EB1B8E54A660311C1A400F94F370B382BE9EA5B37836328BF2C2FADCFDD7C022006BE9C8336F56AE98135CBF6D87ABB47B3F5C38028E1438246078648CA031BF5C221036D9E146EDA0C9E01DF36F4735C39B29E8C8B58BFDB2BCF82E407A1CEEB8ED040FFFFFFFFA11701B6BC31DA3646DBAEBD0042AD7357B14A35B97461E9F2278DEB90FD6838D30000006B483045022100D7CD746B6352CDCF939870F2FC4B119B2F526171E00DA06ADB3359155E5BC03C022022E5126E535BE59FCF2AD6F6850B3F48DE7D5552D49468B00A01B728F4AB7239C221029C4787B4B8514206737095BB1C95E62BB901845E5AB8C4144B06E09C654F8F6CFFFFFFFFA11701B6BC31DA3646DBAEBD0042AD7357B14A35B97461E9F2278DEB90FD6838D20000006B483045022100CBC2A4BC0070EF066FDFC99D7214025E410C368D7711D1F30DB4D0A676C1D7B20220675CB5B255B882408C2797FFA5A25FE652F8B1D6E2CCBD8029905FDBAE88F9FEC22103346CEED4C7E38ECFDEF9DA13316C9549E2E3AB1BE03CEF2E1D799371C315897EFFFFFFFFCA40E64BC0512AD8EB45E5611A5482F609FD69D99C9E0AE4980D50C11B6C67D8000000006B483045022100E48A110972F0783E15EA0E89BD348D1531622872B0E35AB61B79A9098E3CFA5202206893582684F5CF2BDC6158EA4624B63788044E8142EA4247AD6979F66AFA7D48C221029C4787B4B8514206737095BB1C95E62BB901845E5AB8C4144B06E09C654F8F6CFFFFFFFFF47FA4B80212220A78327B2FE5F93263EA6659FFA6BD6D380C1D58C6739BE8D5010000006A473044022056F79F2D88910609ED1D2A83E86702A7794122D45C6433009BEBA328F60969E20220488D7D11D2DEED21A8A2034A537DF86A9319093DF782A54D1C49048D8A8028CEC2210364E1D7C8AB3D509207760BACF81BB050E67322EBF2E905FF309E89ACE13BE894FFFFFFFF1F6FCB9D335E553262F3FB1CA6A826DBBE9428DD579EA51BA6090C83A7D4FCDA010000006A47304402205C9C3FFC78210A7B93912FAC417775EE6DCD8B6794BE36D01C7D0BF36BC408D702201A253C7F4BD2464DED11A837C9EA628A97399632ED04C2FEA22CBD75579E58E8C2210364E1D7C8AB3D509207760BACF81BB050E67322EBF2E905FF309E89ACE13BE894FFFFFFFF09B0858061E61218B0BB5956508F643E3818FA1FBB1400ADA6D994704418DCD9010000006A47304402203FE198B7AB8F61546D62B35A4DF160DB438C84EFFD7067B46C60AF5F27E0CBB502205FB58F426A03427CDA37CCF5B63F672F5BFE71C7E8B791AFDEEACBD1D3595CB1C22103FB41089708436C88CF77E0700CB67ACDE37F255DC4CCDBD7637AA79307269630FFFFFFFF9B1A1B386F7D66899033F7B2AEB6A934CBA1BC2953AD4FE5E16A47EEC5F3FE23000000006A47304402202DDBBB9E92D1446A4F3890657F1F56EC2DC8F41DE864077CFDB41E6C99F75FDE02204553AC6BD3B9AE35DB4664BD18BF57B3E8E9BE84D76E40B78B77E760C36A064EC22103E080628C06E929C254B93A922BD42529A5E96491DFE0472AAF94928478B9EB60FFFFFFFF02FB55CA273FD7916E9C7B8F38D3F0287F9897980C840E0FA10F035DA33DAD47010000006B483045022100AC5FA70052293648A3BE5319C55B4E0A7E579F744CA04593F6EB88E0B88C1BA9022001B3419B5262022A8D5AADBEC1296167D436EE1808CD11CAC22C6B12B382CEB2C22103E080628C06E929C254B93A922BD42529A5E96491DFE0472AAF94928478B9EB60FFFFFFFF770E137F47D0C046AA1F02ED198F0F5EACBA78AED8A12D5B6AC9B169C75CC8ABB50000006A47304402204EBD05E2826D5263973B0C33AA32A6E5213C8378A16CF620E41E0AE27F04A5ED02201C38314E0755513CB720BDAAAACB495945C8B64873F04CCB0AB4ECE98C023543C22103E080628C06E929C254B93A922BD42529A5E96491DFE0472AAF94928478B9EB60FFFFFFFF770E137F47D0C046AA1F02ED198F0F5EACBA78AED8A12D5B6AC9B169C75CC8ABB40000006B483045022100CEE6BBBA8DFB309895A264091C9E9965EA71559F13DB22CE66DCD6A9E215E9DF0220355620462931985C870E5793C2F7222440CE468B1AD339BE4A85BADB81B25C08C22103D7558C265481BC9009884F2C6E629E7B6183D97538E9623503FC8CF5C7363D62FFFFFFFF249E0A85AC5C5F61771C6A7B1121C11FE2B68BCCA8734286AB936F10F0DF4C9E000000006B483045022100A1F45E58C823833DFA5BC5B7FE96618670911C9F1961B6E79CCBCC5D951859BB022034373BFF50DF19DD0E12736DAC6D9C4F5371C373CD6FB6CA0C07AF66AFD7F911C22103F9832BCBECE37C09BF91A46792F89C12C400F0E23F3B959CEA9EF1A9F5668888FFFFFFFF864243C3AC4F36396369D2A71FF4F0AB9C3BC0D3F12A5B396980542BE38C9E64330100006A473044022065A5B6C567A05E90B6C236678AEDBC6FE93371AC2F64D1EC0BF3F294EEC3A53202202E28C99E9E285DA66BAC4EEF042BABCD94A41E43A284F31A97D0A45CBE828A66C22103F9832BCBECE37C09BF91A46792F89C12C400F0E23F3B959CEA9EF1A9F5668888FFFFFFFF864243C3AC4F36396369D2A71FF4F0AB9C3BC0D3F12A5B396980542BE38C9E643501000069463043021F5601776FD074AB9A0FC636661D156CF07BF5B15B6648C5BC66D05DE4D3A663022048F33208CED52287867C6E56498553998ED9F5FF46FA5A5F2B14EC6F6C9F1FC6C221038948C2F32F21FF2E33B00D16E3204AF5EF888331C74D237709CA4D4654BBBB80FFFFFFFF864243C3AC4F36396369D2A71FF4F0AB9C3BC0D3F12A5B396980542BE38C9E64340100006B483045022100ED170557BCF179486B0CD35E56717721AA948941E84234F7CACC5EE3C24C3110022063B0CFBDB9C6C8F2AEBA01EFE48ED5B273006B8B6D238C1C1282763F7BA0852FC22102F72539E17B2A9FB12999AD5AEA4FEECB2CE50574B56B5CEEE4D02D8CD07090B7FFFFFFFF51386BF256B3987E0C6404D27D06E3E53B0DE6904A419F6B8DF038F13988A8CA000000006B483045022100E34C6EA96AF4701F0CF16E898E979EBC3EB214DDA8B485AEE811E21F1C34782D022047EAD42030B2E67B15B2A3417A0420D77467C71CA31AC06E759415E2ED1E73B0C221038948C2F32F21FF2E33B00D16E3204AF5EF888331C74D237709CA4D4654BBBB80FFFFFFFF11F69487F837BD1D30C88D6F89800760FD914CBEA11EFEFB97CC2EF8467FD29C000000006A473044022079A8AE9B2F18D6C8A8C57F925C8EDE9E7DC4E9B029A08FF04FB0E7955B18E8DA0220050B99D687C43AF8CADC311DB062309B2232D0A978AC6E39328A562D3965243DC221038948C2F32F21FF2E33B00D16E3204AF5EF888331C74D237709CA4D4654BBBB80FFFFFFFFE10CEAE7D2BB2D7C60DD853E6DF8540D352C6FCA363553690425F267F4E36BB5380000006B4830450221009CF2B05A6B673E2AFF83CDA2B52D2FEF073DC8DC84C544CB5F978532A626CC7502206B6F69D943286ED45E7A5F430DEE8C6475F95EB8E557A2E2C5785F60B4E5E5E3C221022586C020EC9DF598D68F69967E61123B8F487CEFF465C8A1A0BCD377C0D4C608FFFFFFFFFBC6C11521941FBBB72A0F3B68D609F66419586D47ED2F313C64181918A04A92010000006B483045022100BEDFA3ADCBF41A099F4372746682F305A5245E08FA137801E7D4EBDE8E7EDEED02206D15AFECC651B8F6C65B59B8844C2088AA154625746A8A02C617D99277D95895C22103987C11B7D23C49817D6164B9C57CE5C845BE9E11342EBCF19095A7486B9BF147FFFFFFFF5D08873B553F347F83F8B30740C5DCBB7586E22A121ADF1888DA6F23F2C253646D0000006A47304402202E6E19291842A0390CA9098510F686D993D02F7A5C01305E5B7EF075BBBEC92E022031C1E35D8DE8F62FA015249FAD699DCA3BD7D48C60FA262C4A25872A99885E98C22103987C11B7D23C49817D6164B9C57CE5C845BE9E11342EBCF19095A7486B9BF147FFFFFFFF5D08873B553F347F83F8B30740C5DCBB7586E22A121ADF1888DA6F23F2C253646C0000006A473044022010920B2B3465ECF21A685884AD54E041C54B0CC73DE7A988921C742B06BEB51302203DB46BD95FEBD29A69008A214A0E7ED65B6B49FB5C96DD086ED10851B7C55B3DC2210239F7060641B0E9A8ED1365420BA2987479ABD66206275067E4EAC21FDCE2AF5AFFFFFFFF73D4D99BA348D4DA8E7F221709280F16A14B4C1E72C1A0E24AD5FC8F09CEED7D010000006A4730440220584F82CBCD237083BE0B5C80645AB8A31C0EAD5C140BD5C299EA3B7270ADADF40220429CAD186E80F0936528B2A3313EEF8A0BC67403969880BF0C1E762FCF82A062C2210239F7060641B0E9A8ED1365420BA2987479ABD66206275067E4EAC21FDCE2AF5AFFFFFFFF0843CB3AD2622892163DF29617F45A799E09B667AD707AD6FE7D0C2FF6FA0248010000006B483045022100DE499AD82B27200F140417C92D2BB7223F4A51AA4E3B3EC0942FFADCA8572F990220587EA05565349E79CA85DFEEE6617335BF50DD56CC0A73434478B867927253D7C2210239F7060641B0E9A8ED1365420BA2987479ABD66206275067E4EAC21FDCE2AF5AFFFFFFFF7E3EFF23768186357CD9E23A3C5E64D7CCDF778D4625C5FD7AF8AA0BA26D18B1010000006A47304402201667B3A2445F77BCD6A4A9DCB87B052E50189F8F261847F165EA6AA8C30204B8022034A449DCEED01B782EEB764B1453A7696B6F45BCDF58F5A16242A27B40254A26C2210205EB0CF0442AC7CF95F237F83631F3A71A769F14070BFBA130E7F6446D0FDA89FFFFFFFF7BD7CA433910CD9CD3A31E3C526C8A08F56218ABEBB8FA7B6D7F9013770903B7060000006B483045022100CBE66D90AF66E7B2098644D489E761D2E1A017DA1BCF514F6EB9CC0D143D3E29022028C3D949EBEB493C630EBA6B94E963DEE224F82E0CAFA688DCE82BF2E3E33029C2210205EB0CF0442AC7CF95F237F83631F3A71A769F14070BFBA130E7F6446D0FDA89FFFFFFFFC06A85664B630EC529F066F082CD4ECE9C6D627B4A25FA052A4321CE201F5249000000006B483045022100B8E3DBB1B95253947D66224F2B56D4AD32CEE62862AA6079BBFDB2A29097384C02207B06BAFDD798EBFC1042952A214EE0095AC456E4EC7ADCD2D7643AC940E37808C22102E6A2C34586C6A2F9F9D8247622E03E2427D8DA8BAD7069B5FBD4BAB7CFD495BEFFFFFFFF5455D0E0DAF167EA4DD6268EBF681F5B627E3CDB95A64E45B46504B47DE7559B010000006A47304402202FB18936EAA9E7574D68B64FD3A72163DC02F36E76105F6230B69B9A8CE8186E02200669E0FF51A609CF52F2D484CF90DECC7E0F288815D889DD54A208FDAFCB0480C22102E6A2C34586C6A2F9F9D8247622E03E2427D8DA8BAD7069B5FBD4BAB7CFD495BEFFFFFFFF0FC11392D3D66CE589DBEE6396A9C91906E94E5FFB0F10582DD84DC27C139549010000006B483045022100B1B780C18EE1B24A67756E15ED487626247718743B25781E8DCEF385817EBA0A0220422935FE91405FD3E2834EBE03EA27DEA2AD73F2E5A32798D3EFAA28A11B0E45C22102D54A842BF3053DA8139191C78DD95859326551C14D33317232240E825AC86721FFFFFFFF5C81D63ACF4A9539158B16F116C9FE16E61AD2EAE8627B0DAF6E5E27D7065BCE4B0000006A473044022070BEAC59696981AB7E13CB99C8AA5EBDA64AB3B2CEFC4197760480B24473C62A02201AC5EA4E1AA854C7CF641A70D5629CE17D3101D0F29F383EBFD300D11B8355F7C22103E0C3031D39F82DCED6FE23F7DAEF43C1C2AA37279E6CACFCC3D65C20896EFAFEFFFFFFFFA832AAD47D0F6C088C259B108C1234866D824B63081D056889560A63987A9F61000000006B483045022100F67205F32BE5981277C403ADD7DDCF355760545FA5F07B5221AC51AD39B5D6240220015D5AC3AE684183E92F128C96B8C4FBE37D581A2238B55548D0FAE5188C93D0C221030A82429D655A883ABB84A6F494ED0F584FAE70AF76F6FFE089FC858DFF6791CAFFFFFFFF9F7AB7BD8B01B35936A0806314FBA6E05978B00B588809CBC1BFE440BE48F437010000006B483045022100B0E893E5300216E39CBA60AA01BBCF233024A364F6688305CBB5A23FD99A9DDB02200BE2E288377E83222C066A4647EEE4A0F8DB1289034F19C75B029071A74B1BB3C221028AA47294780FCE86047AD43B106B887101311EF2EC15CF8CC781A5E94E941B87FFFFFFFF437A577E1B156B11BA5D3D4F77883778B8A16344DE7A493337A48A4277E3501F640000006B4830450221008BDFE07288CC912878F66E451DA2067E02FD2169B32C42ADC226CA0AC588ABFC02207F3F185DB742C755F554539C2DDAE99DB84BF31198623F3D36B28A6040F13187C221028DC193FA0BAE51229C0D913B37B4B85E7D8657C67E6B39DE55F0F829F3E56F97FFFFFFFFEB46CAC62C55714409DC0CB9DEB430A28BDF64DE9F67D2A462E6901B4D633376010000006A47304402203627468E6F210ABD49276436DC5A76DF6160D25650C62F5943140AC70FECF39302202294C59CF141219551382ECCE8D529F346A88413070DC90FB11B3AFA24C9DDE5C2210375727B6DF18C46DA978E03F1197AD63F3A7A2EB59ECC6C808F01CF01DF4CC462FFFFFFFFFE263AF23E8A0656DA85D0E776CD26B77EB606869C41119CF0211DC3EB7FACD1210100006B483045022100967F8B5E10858E507C64F9DA6FF840133FD5A76E515C3CFDF88833E9819733F2022052B33CD8CD3AB5CF745C75136F2CDF675620BB94D09616117567FD22D08AD052C2210375727B6DF18C46DA978E03F1197AD63F3A7A2EB59ECC6C808F01CF01DF4CC462FFFFFFFFFE263AF23E8A0656DA85D0E776CD26B77EB606869C41119CF0211DC3EB7FACD1200100006B483045022100ADC229F8037EB7B3D08D6DE7A0DEAAE2874D7B943406D9ADAEC34899A7CC0B62022059DE20822F8E1DF474C0C763EAB20EB1AADC9DAC2EBB3D685CB24EC6917AFC49C221027ED09AC05B9215F00B6F8BE59CEC79284542F5E8C1D17AC660B2C296FCEE931BFFFFFFFF232740426EDFE1EA3337FB4438252AA67FB144C6CB1DAC76FEBB16BB954C6ABA000000006B483045022100DB65D8077D5EA9C886629F328BFCAC9ACBA3FF83E50EA18C360CE22CD6DC3BDC022001759AF276AFE21C13A66539008DC5F0469129A3FB7A51703B2FE416047C8A1CC221027ED09AC05B9215F00B6F8BE59CEC79284542F5E8C1D17AC660B2C296FCEE931BFFFFFFFF09537489C63ED62DF8D069AEFD16BF4775E1D9878F0BE9EAC4AC2CB3A8169DAE260000006B483045022100D0CAA6FD70BF80C6E936F4738221F874E9C620FE1CA96BC0D87F23FF863B33DE0220124B342E241E41C2645DC4181A75239618D267E64BBDAB7A72109BFAB89FE784C22102C4559C96B87528C3B2385DC63216B0EEE1E25524E9E45CBB7577DEF21B1D62B9FFFFFFFF3739FA73213ED1440431274667DDCEA593DFBDFADFF26F37359BC06492BBB0E59B0000006B48304502210099AA3BD609A06C875D0F584B0A6644387179ACB6F63C690C6FF20B650653259802205898DD42BC06A8F8D1A74A2F74CCBA7B0D6DCBDA51A9B7ADD12E5F4F13121CCFC2210366C2029F74160CBA941383501C988D37BF932629F97B4E07DF1A339EC25ADB71FFFFFFFFC34D896F7B4EAE1344A02398292A2FDDD464E15A0C3321FF17D3B96D92D8FB64340000006B483045022100F32667A5734DDA65A6DDF9DFA789907B1ABBEBB0062CD694FA6E2A57A13178A202205BAF300DFADA245B470BA87794219E8173723FF3AC6FEA06296D23297375BF45C2210268C6B69A5BC61E1F3452D5828D7D2D8FBD4AAC371665ADB17973198377DD10D4FFFFFFFFCFD345CB9C6D4574D28EF1E0704B2657434FBAE1521F27D9AE1E005039DF4D92940000006B483045022100F228CC33D6EAAE7C0631741D1D0DD1EE02ECF725DDEFB1D02C877B3E449AA588022052C50C407B0217EE829BC1392971198ED7D08D18A5ABF90C13D9A81F20D7EA65C2210265BD8F8378E28817B5CBE47B08E326FC9972F27D1A354A85F43888507B10A497FFFFFFFF4DFCB8A82E6BFA8EB78BA4E66F0142B49D685D3036094A7F490DB544007E2292560000006B483045022100A82557798CCA2E6D8F00FBB49A9DE767BB2079E90B615DF29E7F44A870BBA43C02207B2B038237D55F962046B8046E53DF428999D716EEC2B980A927ADD5AE3A607AC22102463CABC398AAC0B7239F1AB82D0794B4E9FF87D4DBBE8747E5A94586485013DCFFFFFFFFEAEACA9F9CDE43599A95F529769BE324C910E0BE55BC84E1F1E92F0DE60F82842A0000006A473044022041765D681A868D6898F1931ECA896B624C7796DF89A7C80004AEFCD4A84D0A19022053ABCE69D529BE59BBC859D4314C2E093FB2C24823001A396DCE4CD7B2F21AA7C2210364BB8517C6A28CF7253DAEBBBA7064A4216125DE6476426E74480A3371B92D42FFFFFFFF25DB850D2664BA6B4DEADC76366DA35C1780C4B937E6DF473C602B49C2F47688380100006A47304402202145BEFCBD10A3D97AF74E264AEFBB6931227FF723BE6A680D277B185E25919902205C1769C6BF8F036F57B092F428C06E39081AF979DE35415AF6C74B294BDD4211C22103B04A47F53CF3BB0F7B00088D453E36618148B9261FAEF8CE8F6B3FA3DFEFBDCAFFFFFFFF01031864CD2E0000001976A91465BD7B5E75C7450F77976954A91DE75C73BEB4CE88AC00000000`
|