@bsv/wallet-toolbox 1.3.22 → 1.3.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/docs/client.md +99 -59
- package/docs/storage.md +55 -75
- package/docs/wallet.md +99 -59
- package/mobile/out/src/Wallet.d.ts +1 -1
- package/mobile/out/src/Wallet.d.ts.map +1 -1
- package/mobile/out/src/Wallet.js +16 -6
- package/mobile/out/src/Wallet.js.map +1 -1
- package/mobile/out/src/WalletPermissionsManager.d.ts.map +1 -1
- package/mobile/out/src/WalletPermissionsManager.js.map +1 -1
- package/mobile/out/src/index.mobile.d.ts +0 -2
- package/mobile/out/src/index.mobile.d.ts.map +1 -1
- package/mobile/out/src/index.mobile.js +0 -2
- package/mobile/out/src/index.mobile.js.map +1 -1
- package/mobile/out/src/monitor/Monitor.d.ts.map +1 -1
- package/mobile/out/src/monitor/Monitor.js +2 -4
- package/mobile/out/src/monitor/Monitor.js.map +1 -1
- package/mobile/out/src/monitor/tasks/TaskNewHeader.d.ts +1 -1
- package/mobile/out/src/monitor/tasks/TaskNewHeader.d.ts.map +1 -1
- package/mobile/out/src/sdk/WalletStorage.interfaces.d.ts +14 -1
- package/mobile/out/src/sdk/WalletStorage.interfaces.d.ts.map +1 -1
- package/mobile/out/src/services/chaintracker/chaintracks/Api/BlockHeaderApi.d.ts.map +1 -0
- package/mobile/out/src/services/chaintracker/chaintracks/Api/BlockHeaderApi.js.map +1 -0
- package/mobile/out/src/services/chaintracker/chaintracks/ChaintracksServiceClient.d.ts +1 -1
- package/mobile/out/src/services/chaintracker/chaintracks/ChaintracksServiceClient.d.ts.map +1 -1
- package/mobile/out/src/services/chaintracker/chaintracks/index.d.ts +1 -1
- package/mobile/out/src/services/chaintracker/chaintracks/index.d.ts.map +1 -1
- package/mobile/out/src/services/chaintracker/chaintracks/index.js +1 -1
- package/mobile/out/src/services/chaintracker/chaintracks/index.js.map +1 -1
- package/mobile/out/src/signer/methods/internalizeAction.d.ts +2 -2
- package/mobile/out/src/signer/methods/internalizeAction.d.ts.map +1 -1
- package/mobile/out/src/signer/methods/internalizeAction.js.map +1 -1
- package/mobile/out/src/storage/StorageIdb.d.ts +2 -1
- package/mobile/out/src/storage/StorageIdb.d.ts.map +1 -1
- package/mobile/out/src/storage/StorageIdb.js +63 -29
- package/mobile/out/src/storage/StorageIdb.js.map +1 -1
- package/mobile/out/src/storage/StorageProvider.d.ts +4 -4
- package/mobile/out/src/storage/StorageProvider.d.ts.map +1 -1
- package/mobile/out/src/storage/StorageProvider.js +35 -26
- package/mobile/out/src/storage/StorageProvider.js.map +1 -1
- package/mobile/out/src/storage/StorageReader.d.ts +2 -1
- package/mobile/out/src/storage/StorageReader.d.ts.map +1 -1
- package/mobile/out/src/storage/StorageReader.js +45 -11
- package/mobile/out/src/storage/StorageReader.js.map +1 -1
- package/mobile/out/src/storage/StorageReaderWriter.d.ts +2 -1
- package/mobile/out/src/storage/StorageReaderWriter.d.ts.map +1 -1
- package/mobile/out/src/storage/StorageReaderWriter.js +29 -29
- package/mobile/out/src/storage/StorageReaderWriter.js.map +1 -1
- package/mobile/out/src/storage/StorageSyncReader.d.ts +2 -1
- package/mobile/out/src/storage/StorageSyncReader.d.ts.map +1 -1
- package/mobile/out/src/storage/StorageSyncReader.js +36 -3
- package/mobile/out/src/storage/StorageSyncReader.js.map +1 -1
- package/mobile/out/src/storage/WalletStorageManager.d.ts +2 -2
- package/mobile/out/src/storage/WalletStorageManager.d.ts.map +1 -1
- package/mobile/out/src/storage/index.mobile.d.ts +1 -1
- package/mobile/out/src/storage/index.mobile.js +1 -1
- package/mobile/out/src/storage/methods/generateChange.d.ts +0 -24
- package/mobile/out/src/storage/methods/generateChange.d.ts.map +1 -1
- package/mobile/out/src/storage/methods/generateChange.js +2 -50
- package/mobile/out/src/storage/methods/generateChange.js.map +1 -1
- package/mobile/out/src/storage/methods/getBeefForTransaction.js +3 -2
- package/mobile/out/src/storage/methods/getBeefForTransaction.js.map +1 -1
- package/mobile/out/src/storage/methods/internalizeAction.d.ts +2 -10
- package/mobile/out/src/storage/methods/internalizeAction.d.ts.map +1 -1
- package/mobile/out/src/storage/methods/internalizeAction.js +16 -1
- package/mobile/out/src/storage/methods/internalizeAction.js.map +1 -1
- package/mobile/out/src/storage/methods/processAction.d.ts +16 -1
- package/mobile/out/src/storage/methods/processAction.d.ts.map +1 -1
- package/mobile/out/src/storage/methods/processAction.js +4 -1
- package/mobile/out/src/storage/methods/processAction.js.map +1 -1
- package/mobile/out/src/storage/methods/utils.d.ts +25 -0
- package/mobile/out/src/storage/methods/utils.d.ts.map +1 -0
- package/mobile/out/src/storage/methods/utils.js +53 -0
- package/mobile/out/src/storage/methods/utils.js.map +1 -0
- package/mobile/out/src/storage/remoting/StorageClient.d.ts +2 -2
- package/mobile/out/src/storage/remoting/StorageClient.d.ts.map +1 -1
- package/mobile/out/src/storage/remoting/StorageClient.js.map +1 -1
- package/mobile/out/src/storage/remoting/StorageMobile.d.ts +283 -0
- package/mobile/out/src/storage/remoting/StorageMobile.d.ts.map +1 -0
- package/mobile/out/src/storage/remoting/StorageMobile.js +477 -0
- package/mobile/out/src/storage/remoting/StorageMobile.js.map +1 -0
- package/mobile/out/src/utility/utilityHelpers.d.ts +1 -1
- package/mobile/out/src/utility/utilityHelpers.d.ts.map +1 -1
- package/mobile/out/src/utility/utilityHelpers.js +3 -3
- package/mobile/out/src/utility/utilityHelpers.js.map +1 -1
- package/mobile/package-lock.json +5 -6
- package/mobile/package.json +1 -1
- package/out/src/Wallet.d.ts +1 -1
- package/out/src/Wallet.d.ts.map +1 -1
- package/out/src/Wallet.js +16 -6
- package/out/src/Wallet.js.map +1 -1
- package/out/src/WalletPermissionsManager.d.ts.map +1 -1
- package/out/src/WalletPermissionsManager.js.map +1 -1
- package/out/src/index.mobile.d.ts +0 -2
- package/out/src/index.mobile.d.ts.map +1 -1
- package/out/src/index.mobile.js +0 -2
- package/out/src/index.mobile.js.map +1 -1
- package/out/src/monitor/Monitor.d.ts.map +1 -1
- package/out/src/monitor/Monitor.js +2 -4
- package/out/src/monitor/Monitor.js.map +1 -1
- package/out/src/monitor/tasks/TaskNewHeader.d.ts +1 -1
- package/out/src/monitor/tasks/TaskNewHeader.d.ts.map +1 -1
- package/out/src/sdk/WalletStorage.interfaces.d.ts +14 -1
- package/out/src/sdk/WalletStorage.interfaces.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Api/BlockHeaderApi.d.ts.map +1 -0
- package/out/src/services/chaintracker/chaintracks/Api/BlockHeaderApi.js.map +1 -0
- package/out/src/services/chaintracker/chaintracks/ChaintracksServiceClient.d.ts +1 -1
- package/out/src/services/chaintracker/chaintracks/ChaintracksServiceClient.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/index.d.ts +1 -1
- package/out/src/services/chaintracker/chaintracks/index.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/index.js +1 -1
- package/out/src/services/chaintracker/chaintracks/index.js.map +1 -1
- package/out/src/services/chaintracker/chaintracks/util/blockHeaderUtilities.d.ts +144 -0
- package/out/src/services/chaintracker/chaintracks/util/blockHeaderUtilities.d.ts.map +1 -0
- package/out/src/services/chaintracker/chaintracks/util/blockHeaderUtilities.js +463 -0
- package/out/src/services/chaintracker/chaintracks/util/blockHeaderUtilities.js.map +1 -0
- package/out/src/services/chaintracker/chaintracks/util/dirtyHashes.d.ts +20 -0
- package/out/src/services/chaintracker/chaintracks/util/dirtyHashes.d.ts.map +1 -0
- package/out/src/services/chaintracker/chaintracks/util/dirtyHashes.js +31 -0
- package/out/src/services/chaintracker/chaintracks/util/dirtyHashes.js.map +1 -0
- package/out/src/signer/methods/internalizeAction.d.ts +2 -2
- package/out/src/signer/methods/internalizeAction.d.ts.map +1 -1
- package/out/src/signer/methods/internalizeAction.js.map +1 -1
- package/out/src/storage/StorageIdb.d.ts +2 -1
- package/out/src/storage/StorageIdb.d.ts.map +1 -1
- package/out/src/storage/StorageIdb.js +63 -29
- package/out/src/storage/StorageIdb.js.map +1 -1
- package/out/src/storage/StorageKnex.d.ts +1 -1
- package/out/src/storage/StorageKnex.d.ts.map +1 -1
- package/out/src/storage/StorageKnex.js +10 -6
- package/out/src/storage/StorageKnex.js.map +1 -1
- package/out/src/storage/StorageProvider.d.ts +4 -4
- package/out/src/storage/StorageProvider.d.ts.map +1 -1
- package/out/src/storage/StorageProvider.js +35 -26
- package/out/src/storage/StorageProvider.js.map +1 -1
- package/out/src/storage/StorageReader.d.ts +2 -1
- package/out/src/storage/StorageReader.d.ts.map +1 -1
- package/out/src/storage/StorageReader.js +45 -11
- package/out/src/storage/StorageReader.js.map +1 -1
- package/out/src/storage/StorageReaderWriter.d.ts +2 -1
- package/out/src/storage/StorageReaderWriter.d.ts.map +1 -1
- package/out/src/storage/StorageReaderWriter.js +29 -29
- package/out/src/storage/StorageReaderWriter.js.map +1 -1
- package/out/src/storage/StorageSyncReader.d.ts +2 -1
- package/out/src/storage/StorageSyncReader.d.ts.map +1 -1
- package/out/src/storage/StorageSyncReader.js +36 -3
- package/out/src/storage/StorageSyncReader.js.map +1 -1
- package/out/src/storage/WalletStorageManager.d.ts +2 -2
- package/out/src/storage/WalletStorageManager.d.ts.map +1 -1
- package/out/src/storage/__test/StorageIdb.test.js +1 -0
- package/out/src/storage/__test/StorageIdb.test.js.map +1 -1
- package/out/src/storage/__test/adminStats.man.test.js +2 -0
- package/out/src/storage/__test/adminStats.man.test.js.map +1 -1
- package/out/src/storage/index.mobile.d.ts +1 -1
- package/out/src/storage/index.mobile.js +1 -1
- package/out/src/storage/methods/generateChange.d.ts +0 -24
- package/out/src/storage/methods/generateChange.d.ts.map +1 -1
- package/out/src/storage/methods/generateChange.js +2 -50
- package/out/src/storage/methods/generateChange.js.map +1 -1
- package/out/src/storage/methods/getBeefForTransaction.js +3 -2
- package/out/src/storage/methods/getBeefForTransaction.js.map +1 -1
- package/out/src/storage/methods/internalizeAction.d.ts +2 -10
- package/out/src/storage/methods/internalizeAction.d.ts.map +1 -1
- package/out/src/storage/methods/internalizeAction.js +16 -1
- package/out/src/storage/methods/internalizeAction.js.map +1 -1
- package/out/src/storage/methods/processAction.d.ts +16 -1
- package/out/src/storage/methods/processAction.d.ts.map +1 -1
- package/out/src/storage/methods/processAction.js +4 -1
- package/out/src/storage/methods/processAction.js.map +1 -1
- package/out/src/storage/methods/utils.Buffer.d.ts +21 -0
- package/out/src/storage/methods/utils.Buffer.d.ts.map +1 -0
- package/out/src/storage/methods/utils.Buffer.js +37 -0
- package/out/src/storage/methods/utils.Buffer.js.map +1 -0
- package/out/src/storage/methods/utils.d.ts +25 -0
- package/out/src/storage/methods/utils.d.ts.map +1 -0
- package/out/src/storage/methods/utils.js +53 -0
- package/out/src/storage/methods/utils.js.map +1 -0
- package/out/src/storage/remoting/StorageClient.d.ts +2 -2
- package/out/src/storage/remoting/StorageClient.d.ts.map +1 -1
- package/out/src/storage/remoting/StorageClient.js.map +1 -1
- package/out/src/storage/remoting/StorageMobile.d.ts +283 -0
- package/out/src/storage/remoting/StorageMobile.d.ts.map +1 -0
- package/out/src/storage/remoting/StorageMobile.js +477 -0
- package/out/src/storage/remoting/StorageMobile.js.map +1 -0
- package/out/src/utility/Format.d.ts +14 -0
- package/out/src/utility/Format.d.ts.map +1 -0
- package/out/src/utility/Format.js +167 -0
- package/out/src/utility/Format.js.map +1 -0
- package/out/src/utility/utilityHelpers.d.ts +1 -1
- package/out/src/utility/utilityHelpers.d.ts.map +1 -1
- package/out/src/utility/utilityHelpers.js +3 -3
- package/out/src/utility/utilityHelpers.js.map +1 -1
- package/out/test/Wallet/support/operations.man.test.js +18 -138
- package/out/test/Wallet/support/operations.man.test.js.map +1 -1
- package/out/test/Wallet/support/reqErrorReview.2025.05.06.man.test.d.ts +2 -0
- package/out/test/Wallet/support/reqErrorReview.2025.05.06.man.test.d.ts.map +1 -0
- package/out/test/Wallet/support/reqErrorReview.2025.05.06.man.test.js +385 -0
- package/out/test/Wallet/support/reqErrorReview.2025.05.06.man.test.js.map +1 -0
- package/out/test/utils/TestUtilsWalletStorage.d.ts +5 -0
- package/out/test/utils/TestUtilsWalletStorage.d.ts.map +1 -1
- package/out/test/utils/TestUtilsWalletStorage.js +20 -0
- package/out/test/utils/TestUtilsWalletStorage.js.map +1 -1
- package/out/tsconfig.all.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/Wallet.ts +25 -10
- package/src/WalletPermissionsManager.ts +19 -8
- package/src/index.mobile.ts +0 -2
- package/src/monitor/Monitor.ts +2 -4
- package/src/monitor/tasks/TaskNewHeader.ts +1 -1
- package/src/sdk/WalletStorage.interfaces.ts +16 -1
- package/src/services/chaintracker/chaintracks/ChaintracksServiceClient.ts +1 -1
- package/src/services/chaintracker/chaintracks/index.ts +1 -1
- package/src/services/chaintracker/chaintracks/util/blockHeaderUtilities.ts +490 -0
- package/src/services/chaintracker/chaintracks/util/dirtyHashes.ts +29 -0
- package/src/signer/methods/internalizeAction.ts +2 -2
- package/src/storage/StorageIdb.ts +4 -5
- package/src/storage/StorageKnex.ts +7 -6
- package/src/storage/StorageProvider.ts +34 -26
- package/src/storage/StorageReader.ts +4 -7
- package/src/storage/StorageReaderWriter.ts +4 -8
- package/src/storage/StorageSyncReader.ts +2 -19
- package/src/storage/WalletStorageManager.ts +1 -1
- package/src/storage/__test/StorageIdb.test.ts +1 -0
- package/src/storage/__test/adminStats.man.test.ts +2 -0
- package/src/storage/index.mobile.ts +1 -1
- package/src/storage/methods/generateChange.ts +1 -54
- package/src/storage/methods/getBeefForTransaction.ts +10 -2
- package/src/storage/methods/internalizeAction.ts +22 -14
- package/src/storage/methods/processAction.ts +5 -2
- package/src/storage/methods/utils.Buffer.ts +33 -0
- package/src/storage/methods/utils.ts +56 -0
- package/src/storage/remoting/StorageClient.ts +2 -3
- package/src/storage/remoting/StorageMobile.ts +527 -0
- package/src/utility/Format.ts +133 -0
- package/src/utility/utilityHelpers.ts +2 -2
- package/test/Wallet/support/operations.man.test.ts +20 -125
- package/test/Wallet/support/reqErrorReview.2025.05.06.man.test.ts +359 -0
- package/test/utils/TestUtilsWalletStorage.ts +23 -0
- package/tsconfig.all.json +2 -1
- package/tsconfig.client.json +6 -0
- package/tsconfig.mobile.json +6 -0
- package/mobile/out/src/services/chaintracker/chaintracks/BlockHeaderApi.d.ts.map +0 -1
- package/mobile/out/src/services/chaintracker/chaintracks/BlockHeaderApi.js.map +0 -1
- package/out/src/services/chaintracker/chaintracks/BlockHeaderApi.d.ts.map +0 -1
- package/out/src/services/chaintracker/chaintracks/BlockHeaderApi.js.map +0 -1
- /package/mobile/out/src/services/chaintracker/chaintracks/{BlockHeaderApi.d.ts → Api/BlockHeaderApi.d.ts} +0 -0
- /package/mobile/out/src/services/chaintracker/chaintracks/{BlockHeaderApi.js → Api/BlockHeaderApi.js} +0 -0
- /package/out/src/services/chaintracker/chaintracks/{BlockHeaderApi.d.ts → Api/BlockHeaderApi.d.ts} +0 -0
- /package/out/src/services/chaintracker/chaintracks/{BlockHeaderApi.js → Api/BlockHeaderApi.js} +0 -0
- /package/src/services/chaintracker/chaintracks/{BlockHeaderApi.ts → Api/BlockHeaderApi.ts} +0 -0
package/package.json
CHANGED
package/src/Wallet.ts
CHANGED
|
@@ -721,24 +721,30 @@ export class Wallet implements WalletInterface, ProtoWallet {
|
|
|
721
721
|
return r
|
|
722
722
|
}
|
|
723
723
|
|
|
724
|
-
async
|
|
725
|
-
args:
|
|
724
|
+
async internalizeAction(
|
|
725
|
+
args: InternalizeActionArgs,
|
|
726
726
|
originator?: OriginatorDomainNameStringUnder250Bytes
|
|
727
|
-
): Promise<
|
|
727
|
+
): Promise<InternalizeActionResult> {
|
|
728
728
|
sdk.validateOriginator(originator)
|
|
729
|
+
const { auth, vargs } = this.validateAuthAndArgs(args, sdk.validateInternalizeActionArgs)
|
|
730
|
+
|
|
731
|
+
if (vargs.labels.indexOf(specOpThrowReviewActions) >= 0) throwDummyReviewActions()
|
|
732
|
+
|
|
733
|
+
const r = await internalizeAction(this, auth, args)
|
|
734
|
+
|
|
735
|
+
throwIfUnsuccessfulInternalizeAction(r)
|
|
729
736
|
|
|
730
|
-
const { auth } = this.validateAuthAndArgs(args, sdk.validateAbortActionArgs)
|
|
731
|
-
const r = await this.storage.abortAction(args)
|
|
732
737
|
return r
|
|
733
738
|
}
|
|
734
739
|
|
|
735
|
-
async
|
|
736
|
-
args:
|
|
740
|
+
async abortAction(
|
|
741
|
+
args: AbortActionArgs,
|
|
737
742
|
originator?: OriginatorDomainNameStringUnder250Bytes
|
|
738
|
-
): Promise<
|
|
743
|
+
): Promise<AbortActionResult> {
|
|
739
744
|
sdk.validateOriginator(originator)
|
|
740
|
-
|
|
741
|
-
const
|
|
745
|
+
|
|
746
|
+
const { auth } = this.validateAuthAndArgs(args, sdk.validateAbortActionArgs)
|
|
747
|
+
const r = await this.storage.abortAction(args)
|
|
742
748
|
return r
|
|
743
749
|
}
|
|
744
750
|
|
|
@@ -1000,6 +1006,15 @@ function throwIfAnyUnsuccessfulSignActions(r: SignActionResultX) {
|
|
|
1000
1006
|
throw new sdk.WERR_REVIEW_ACTIONS(ndrs, swrs, r.txid, r.tx)
|
|
1001
1007
|
}
|
|
1002
1008
|
|
|
1009
|
+
function throwIfUnsuccessfulInternalizeAction(r: sdk.StorageInternalizeActionResult) {
|
|
1010
|
+
const ndrs = r.notDelayedResults
|
|
1011
|
+
const swrs = r.sendWithResults
|
|
1012
|
+
|
|
1013
|
+
if (!ndrs || !swrs || swrs.every(r => r.status === 'unproven')) return
|
|
1014
|
+
|
|
1015
|
+
throw new sdk.WERR_REVIEW_ACTIONS(ndrs, swrs, r.txid)
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1003
1018
|
/**
|
|
1004
1019
|
* Throws a WERR_REVIEW_ACTIONS with a full set of properties to test data formats and propagation.
|
|
1005
1020
|
*/
|
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
WalletInterface,
|
|
3
|
+
Utils,
|
|
4
|
+
PushDrop,
|
|
5
|
+
LockingScript,
|
|
6
|
+
Transaction,
|
|
7
|
+
WalletProtocol,
|
|
8
|
+
Base64String,
|
|
9
|
+
PubKeyHex
|
|
10
|
+
} from '@bsv/sdk'
|
|
2
11
|
import { validateCreateActionArgs } from './sdk'
|
|
3
12
|
|
|
4
13
|
////// TODO: ADD SUPPORT FOR ADMIN COUNTERPARTIES BASED ON WALLET STORAGE
|
|
@@ -1576,7 +1585,7 @@ export class WalletPermissionsManager implements WalletInterface {
|
|
|
1576
1585
|
* @param params.basket Optional basket name to filter by
|
|
1577
1586
|
* @returns Array of permission tokens that match the filter criteria
|
|
1578
1587
|
*/
|
|
1579
|
-
public async listBasketAccess(params: { originator?: string
|
|
1588
|
+
public async listBasketAccess(params: { originator?: string; basket?: string } = {}): Promise<PermissionToken[]> {
|
|
1580
1589
|
const basketName = BASKET_MAP.basket
|
|
1581
1590
|
const tags: string[] = []
|
|
1582
1591
|
|
|
@@ -1708,12 +1717,14 @@ export class WalletPermissionsManager implements WalletInterface {
|
|
|
1708
1717
|
* @param verifier Optional verifier to filter by
|
|
1709
1718
|
* @returns Array of permission tokens that match the filter criteria
|
|
1710
1719
|
*/
|
|
1711
|
-
public async listCertificateAccess(
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1720
|
+
public async listCertificateAccess(
|
|
1721
|
+
params: {
|
|
1722
|
+
originator?: string
|
|
1723
|
+
privileged?: boolean
|
|
1724
|
+
certType?: Base64String
|
|
1725
|
+
verifier?: PubKeyHex
|
|
1726
|
+
} = {}
|
|
1727
|
+
): Promise<PermissionToken[]> {
|
|
1717
1728
|
const basketName = BASKET_MAP.certificate
|
|
1718
1729
|
const tags: string[] = []
|
|
1719
1730
|
|
package/src/index.mobile.ts
CHANGED
package/src/monitor/Monitor.ts
CHANGED
|
@@ -133,8 +133,7 @@ export class Monitor {
|
|
|
133
133
|
this._tasks.push(new TaskCheckNoSends(this))
|
|
134
134
|
this._tasks.push(new TaskFailAbandoned(this, 8 * this.oneMinute))
|
|
135
135
|
this._tasks.push(new TaskUnFail(this))
|
|
136
|
-
|
|
137
|
-
//this._tasks.push(new TaskPurge(this, this.defaultPurgeParams, 6 * this.oneHour))
|
|
136
|
+
this._tasks.push(new TaskPurge(this, this.defaultPurgeParams, 6 * this.oneHour))
|
|
138
137
|
this._tasks.push(new TaskReviewStatus(this))
|
|
139
138
|
}
|
|
140
139
|
|
|
@@ -150,8 +149,7 @@ export class Monitor {
|
|
|
150
149
|
this._tasks.push(new TaskCheckNoSends(this))
|
|
151
150
|
this._tasks.push(new TaskFailAbandoned(this, 8 * this.oneMinute))
|
|
152
151
|
this._tasks.push(new TaskUnFail(this))
|
|
153
|
-
|
|
154
|
-
//this._tasks.push(new TaskPurge(this, this.defaultPurgeParams, 6 * this.oneHour))
|
|
152
|
+
this._tasks.push(new TaskPurge(this, this.defaultPurgeParams, 6 * this.oneHour))
|
|
155
153
|
this._tasks.push(new TaskReviewStatus(this))
|
|
156
154
|
}
|
|
157
155
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BlockHeader } from '../../services/chaintracker/chaintracks/BlockHeaderApi'
|
|
1
|
+
import { BlockHeader } from '../../services/chaintracker/chaintracks/Api/BlockHeaderApi'
|
|
2
2
|
import { Monitor } from '../Monitor'
|
|
3
3
|
import { WalletMonitorTask } from './WalletMonitorTask'
|
|
4
4
|
|
|
@@ -155,7 +155,7 @@ export interface WalletStorageWriter extends WalletStorageReader {
|
|
|
155
155
|
abortAction(auth: AuthId, args: AbortActionArgs): Promise<AbortActionResult>
|
|
156
156
|
createAction(auth: AuthId, args: ValidCreateActionArgs): Promise<StorageCreateActionResult>
|
|
157
157
|
processAction(auth: AuthId, args: StorageProcessActionArgs): Promise<StorageProcessActionResults>
|
|
158
|
-
internalizeAction(auth: AuthId, args: InternalizeActionArgs): Promise<
|
|
158
|
+
internalizeAction(auth: AuthId, args: InternalizeActionArgs): Promise<StorageInternalizeActionResult>
|
|
159
159
|
|
|
160
160
|
insertCertificateAuth(auth: AuthId, certificate: TableCertificateX): Promise<number>
|
|
161
161
|
|
|
@@ -267,6 +267,20 @@ export interface StorageProcessActionArgs {
|
|
|
267
267
|
log?: string
|
|
268
268
|
}
|
|
269
269
|
|
|
270
|
+
export interface StorageInternalizeActionResult extends InternalizeActionResult {
|
|
271
|
+
/** true if internalizing outputs on an existing storage transaction */
|
|
272
|
+
isMerge: boolean
|
|
273
|
+
/** txid of transaction being internalized */
|
|
274
|
+
txid: string
|
|
275
|
+
/** net change in change balance for user due to this internalization */
|
|
276
|
+
satoshis: number
|
|
277
|
+
|
|
278
|
+
/** valid iff not isMerge and txid was unknown to storage and non-delayed broadcast was not success */
|
|
279
|
+
sendWithResults?: SendWithResult[]
|
|
280
|
+
/** valid iff not isMerge and txid was unknown to storage and non-delayed broadcast was not success */
|
|
281
|
+
notDelayedResults?: ReviewActionResult[]
|
|
282
|
+
}
|
|
283
|
+
|
|
270
284
|
/**
|
|
271
285
|
* Indicates status of a new Action following a `createAction` or `signAction` in immediate mode:
|
|
272
286
|
* When `acceptDelayedBroadcast` is falses.
|
|
@@ -333,6 +347,7 @@ export interface PurgeResults {
|
|
|
333
347
|
export interface StorageProvenOrReq {
|
|
334
348
|
proven?: TableProvenTx
|
|
335
349
|
req?: TableProvenTxReq
|
|
350
|
+
isNew?: boolean
|
|
336
351
|
}
|
|
337
352
|
|
|
338
353
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
2
|
import { asString, sdk } from '../../../index.client'
|
|
3
3
|
|
|
4
|
-
import { BaseBlockHeader, BlockHeader, isBaseBlockHeader } from './BlockHeaderApi'
|
|
4
|
+
import { BaseBlockHeader, BlockHeader, isBaseBlockHeader } from './Api/BlockHeaderApi'
|
|
5
5
|
|
|
6
6
|
interface FetchStatus<T> {
|
|
7
7
|
status: 'success' | 'error'
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export * from './ChaintracksServiceClient'
|
|
2
|
-
export * from './BlockHeaderApi'
|
|
2
|
+
export * from './Api/BlockHeaderApi'
|
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
import { validateAgainstDirtyHashes } from './dirtyHashes'
|
|
2
|
+
import { BigNumber, Hash, Utils } from '@bsv/sdk'
|
|
3
|
+
|
|
4
|
+
import { promises as fs } from 'fs'
|
|
5
|
+
|
|
6
|
+
import { asArray, asBuffer, asString } from '../../../../utility/utilityHelpers.buffer'
|
|
7
|
+
import { doubleSha256BE, doubleSha256LE } from '../../../../utility/utilityHelpers'
|
|
8
|
+
import { BaseBlockHeader, BlockHeader } from '../Api/BlockHeaderApi'
|
|
9
|
+
import { Chain } from '../../../../sdk/types'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Computes sha256 hash of file contents read as bytes with no encoding.
|
|
13
|
+
* @param filepath Full filepath to file.
|
|
14
|
+
* @param bufferSize Optional read buffer size to use. Defaults to 80,000 bytes.
|
|
15
|
+
* @returns `{hash, length}` where `hash` is base64 string form of file hash and `length` is file length in bytes.
|
|
16
|
+
*/
|
|
17
|
+
export async function sha256HashOfBinaryFile(
|
|
18
|
+
filepath: string,
|
|
19
|
+
bufferSize = 80000
|
|
20
|
+
): Promise<{ hash: string; length: number }> {
|
|
21
|
+
const file = await fs.open(filepath, 'r')
|
|
22
|
+
try {
|
|
23
|
+
let length = 0
|
|
24
|
+
|
|
25
|
+
const sha256 = new Hash.SHA256()
|
|
26
|
+
const readBuf = Buffer.alloc(bufferSize)
|
|
27
|
+
|
|
28
|
+
// eslint-disable-next-line no-constant-condition
|
|
29
|
+
while (true) {
|
|
30
|
+
const rr = await file.read(readBuf, 0, readBuf.length)
|
|
31
|
+
if (!rr.bytesRead) break
|
|
32
|
+
length += rr.bytesRead
|
|
33
|
+
sha256.update(asArray(rr.buffer))
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return { hash: Utils.toBase64(sha256.digest()), length }
|
|
37
|
+
} finally {
|
|
38
|
+
await file.close()
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Validate headers contained in an array of bytes. The headers must be consecutive block headers, 80 bytes long,
|
|
44
|
+
* where the hash of each header equals the previousHash of the following header.
|
|
45
|
+
* @param buffer Buffer of headers to be validated.
|
|
46
|
+
* @param previousHash Expected previousHash of first header.
|
|
47
|
+
* @param offset Optional starting offset within `buffer`.
|
|
48
|
+
* @param count Optional number of headers to validate. Validates to end of buffer if missing.
|
|
49
|
+
* @returns Header hash of last header validated or previousHash if there where none.
|
|
50
|
+
*/
|
|
51
|
+
export function validateBufferOfHeaders(buffer: number[], previousHash: string, offset = 0, count = -1): string {
|
|
52
|
+
if (count < 0) count = Math.floor((buffer.length - offset) / 80)
|
|
53
|
+
count = Math.max(0, count)
|
|
54
|
+
let lastHeaderHash = previousHash
|
|
55
|
+
for (let i = 0; i < count; i++) {
|
|
56
|
+
const headerStart = offset + i * 80
|
|
57
|
+
const headerEnd = headerStart + 80
|
|
58
|
+
if (headerEnd > buffer.length) {
|
|
59
|
+
throw {
|
|
60
|
+
message: `header ${i} missing bytes for header at offset ${headerStart} in buffer of length ${buffer.length}`
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const header = buffer.slice(headerStart, headerEnd)
|
|
64
|
+
const hashPrev = asString(header.slice(4, 36).reverse())
|
|
65
|
+
if (lastHeaderHash !== hashPrev)
|
|
66
|
+
throw { message: `header ${i} invalid previousHash ${lastHeaderHash} vs ${hashPrev}` }
|
|
67
|
+
lastHeaderHash = asString(doubleSha256BE(header))
|
|
68
|
+
validateAgainstDirtyHashes(lastHeaderHash)
|
|
69
|
+
}
|
|
70
|
+
return lastHeaderHash
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @param work chainWork as a BigNumber
|
|
75
|
+
* @returns Converted chainWork value from BN to hex string of 32 bytes.
|
|
76
|
+
*/
|
|
77
|
+
export function workBNtoBuffer(work: BigNumber): string {
|
|
78
|
+
return work.toString(16).padStart(64, '0')
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Returns true if work1 is more work (greater than) work2
|
|
83
|
+
*/
|
|
84
|
+
export function isMoreWork(work1: string, work2: string): boolean {
|
|
85
|
+
return new BigNumber(asArray(work1), 16).gt(new BigNumber(asArray(work2), 16))
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Add two Buffer encoded chainwork values
|
|
90
|
+
* @returns Sum of work1 + work2 as Buffer encoded chainWork value
|
|
91
|
+
*/
|
|
92
|
+
export function addWork(work1: string, work2: string): string {
|
|
93
|
+
const sum = new BigNumber(asArray(work1), 16).add(new BigNumber(asArray(work2), 16))
|
|
94
|
+
return workBNtoBuffer(sum)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Subtract Buffer encoded chainwork values
|
|
99
|
+
* @returns work1 - work2 as Buffer encoded chainWork value
|
|
100
|
+
*/
|
|
101
|
+
export function subWork(work1: string, work2: string): string {
|
|
102
|
+
const sum = new BigNumber(asArray(work1), 16).sub(new BigNumber(asArray(work2), 16))
|
|
103
|
+
return workBNtoBuffer(sum)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Computes "target" value for 4 byte Bitcoin block header "bits" value.
|
|
108
|
+
* @param bits number or converted from Buffer using `readUint32LE`
|
|
109
|
+
* @returns 32 byte Buffer with "target" value
|
|
110
|
+
*/
|
|
111
|
+
export function convertBitsToTarget(bits: number | number[]): BigNumber {
|
|
112
|
+
if (Array.isArray(bits)) bits = readUInt32LE(bits, 0)
|
|
113
|
+
|
|
114
|
+
const shift = (bits >> 24) & 0xff
|
|
115
|
+
const data = bits & 0x007fffff
|
|
116
|
+
|
|
117
|
+
const target = new BigNumber(data)
|
|
118
|
+
if (shift <= 3) {
|
|
119
|
+
target.iushrn(8 * (3 - shift))
|
|
120
|
+
} else {
|
|
121
|
+
target.iushln(8 * (shift - 3))
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return target
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Computes "chainWork" value for 4 byte Bitcoin block header "bits" value.
|
|
129
|
+
* @param bits number or converted from Buffer using `readUint32LE`
|
|
130
|
+
* @returns 32 byte Buffer with "chainWork" value
|
|
131
|
+
*/
|
|
132
|
+
export function convertBitsToWork(bits: number | number[]): string {
|
|
133
|
+
const target = convertBitsToTarget(bits)
|
|
134
|
+
|
|
135
|
+
// convert target to work
|
|
136
|
+
const work = target.notn(256).div(target.addn(1)).addn(1)
|
|
137
|
+
|
|
138
|
+
return work.toString(16).padStart(64, '0')
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function deserializeBaseBlockHeaders(
|
|
142
|
+
buffer: number[],
|
|
143
|
+
offset = 0,
|
|
144
|
+
count?: number | undefined
|
|
145
|
+
): BaseBlockHeader[] {
|
|
146
|
+
const headers: BaseBlockHeader[] = []
|
|
147
|
+
while ((!count || headers.length < count) && offset + 80 <= buffer.length && offset >= 0) {
|
|
148
|
+
headers.push(deserializeBlockHeader(buffer, offset))
|
|
149
|
+
offset += 80
|
|
150
|
+
}
|
|
151
|
+
return headers
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function deserializeBlockHeaders(
|
|
155
|
+
firstHeight: number,
|
|
156
|
+
buffer: number[],
|
|
157
|
+
offset = 0,
|
|
158
|
+
count?: number | undefined
|
|
159
|
+
): BlockHeader[] {
|
|
160
|
+
const headers: BlockHeader[] = []
|
|
161
|
+
let nextHeight = firstHeight
|
|
162
|
+
while ((!count || headers.length < count) && offset + 80 <= buffer.length && offset >= 0) {
|
|
163
|
+
const baseBuffer = buffer.slice(offset, offset + 80)
|
|
164
|
+
const base = deserializeBlockHeader(baseBuffer)
|
|
165
|
+
const header = {
|
|
166
|
+
...base,
|
|
167
|
+
height: nextHeight++,
|
|
168
|
+
hash: asString(blockHash(baseBuffer))
|
|
169
|
+
}
|
|
170
|
+
headers.push(header)
|
|
171
|
+
offset += 80
|
|
172
|
+
}
|
|
173
|
+
return headers
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Extract an array of block hashes and of merkleRoots from a buffer of serialized block headers.
|
|
178
|
+
* @param buffer
|
|
179
|
+
*/
|
|
180
|
+
export function extractHashesAndRoots(buffer: Buffer): { hashes: Buffer[]; merkleRoots: Buffer[] } {
|
|
181
|
+
const hashes: Buffer[] = []
|
|
182
|
+
const merkleRoots: Buffer[] = []
|
|
183
|
+
for (let i = 0; i < buffer.length / 80; i++) {
|
|
184
|
+
const offset = i * 80
|
|
185
|
+
const hash = asBuffer(doubleSha256LE(asArray(buffer.subarray(offset, 80 + offset))).reverse())
|
|
186
|
+
const merkleRoot = buffer.subarray(36 + offset, 68 + offset).reverse()
|
|
187
|
+
hashes.push(hash)
|
|
188
|
+
merkleRoots.push(merkleRoot)
|
|
189
|
+
}
|
|
190
|
+
return { hashes, merkleRoots }
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Given a block header, ensures that its format is correct. This does not
|
|
195
|
+
* check its difficulty or validity relative to the chain of headers.
|
|
196
|
+
*
|
|
197
|
+
* Throws on format errors.
|
|
198
|
+
*
|
|
199
|
+
* @param The header to validate
|
|
200
|
+
*
|
|
201
|
+
* @returns true if the header is correctly formatted
|
|
202
|
+
*/
|
|
203
|
+
export function validateHeaderFormat(header: BlockHeader): void {
|
|
204
|
+
const ALLOWED_KEYS = {
|
|
205
|
+
version: true,
|
|
206
|
+
previousHash: true,
|
|
207
|
+
merkleRoot: true,
|
|
208
|
+
time: true,
|
|
209
|
+
bits: true,
|
|
210
|
+
nonce: true,
|
|
211
|
+
height: true,
|
|
212
|
+
hash: true
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const UINT_MAX = 0xffffffff
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Root object checks
|
|
219
|
+
*/
|
|
220
|
+
if (typeof header === 'undefined') {
|
|
221
|
+
throw new Error('Missing header.')
|
|
222
|
+
}
|
|
223
|
+
if (typeof header !== 'object') {
|
|
224
|
+
throw new Error('Header must be an object.')
|
|
225
|
+
}
|
|
226
|
+
if (!Object.keys(header).every(key => ALLOWED_KEYS[key])) {
|
|
227
|
+
throw new Error('Header contains extra properties.')
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Version
|
|
232
|
+
*/
|
|
233
|
+
if (typeof header.version !== 'number') {
|
|
234
|
+
throw new Error('Header version must be a number.')
|
|
235
|
+
}
|
|
236
|
+
if (!Number.isInteger(header.version)) {
|
|
237
|
+
throw new Error('Header version must be an integer.')
|
|
238
|
+
}
|
|
239
|
+
if (header.version < 0 || header.version > UINT_MAX) {
|
|
240
|
+
throw new Error(`Header version must be between 0 and ${UINT_MAX}.`)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Height
|
|
245
|
+
*/
|
|
246
|
+
if (typeof header.height !== 'number') {
|
|
247
|
+
throw new Error('Header height must be a number.')
|
|
248
|
+
}
|
|
249
|
+
if (!Number.isInteger(header.height)) {
|
|
250
|
+
throw new Error('Header height must be an integer.')
|
|
251
|
+
}
|
|
252
|
+
if (header.height < 0 || header.height > UINT_MAX / 2) {
|
|
253
|
+
throw new Error(`Header version must be between 0 and ${UINT_MAX / 2}.`)
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Previous hash
|
|
258
|
+
*/
|
|
259
|
+
if (header.previousHash.length !== 64) {
|
|
260
|
+
throw new Error('Header previousHash must be 32 hex bytes.')
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Merkle root
|
|
265
|
+
*/
|
|
266
|
+
if (header.merkleRoot.length !== 64) {
|
|
267
|
+
throw new Error('Header merkleRoot must be 32 hex bytes.')
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Time
|
|
272
|
+
*/
|
|
273
|
+
if (typeof header.time !== 'number') {
|
|
274
|
+
throw new Error('Header time must be a number.')
|
|
275
|
+
}
|
|
276
|
+
if (!Number.isInteger(header.time)) {
|
|
277
|
+
throw new Error('Header time must be an integer.')
|
|
278
|
+
}
|
|
279
|
+
if (header.time < 0 || header.time > UINT_MAX) {
|
|
280
|
+
throw new Error(`Header time must be between 0 and ${UINT_MAX}.`)
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Bits
|
|
285
|
+
*/
|
|
286
|
+
if (typeof header.bits !== 'number') {
|
|
287
|
+
throw new Error('Header bits must be a number.')
|
|
288
|
+
}
|
|
289
|
+
if (!Number.isInteger(header.bits)) {
|
|
290
|
+
throw new Error('Header bits must be an integer.')
|
|
291
|
+
}
|
|
292
|
+
if (header.bits < 0 || header.bits > UINT_MAX) {
|
|
293
|
+
throw new Error(`Header bits must be between 0 and ${UINT_MAX}.`)
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Nonce
|
|
298
|
+
*/
|
|
299
|
+
if (typeof header.nonce !== 'number') {
|
|
300
|
+
throw new Error('Header nonce must be a number.')
|
|
301
|
+
}
|
|
302
|
+
if (!Number.isInteger(header.nonce)) {
|
|
303
|
+
throw new Error('Header nonce must be an integer.')
|
|
304
|
+
}
|
|
305
|
+
if (header.nonce < 0 || header.nonce > UINT_MAX) {
|
|
306
|
+
throw new Error(`Header nonce must be between 0 and ${UINT_MAX}.`)
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Hash
|
|
311
|
+
*/
|
|
312
|
+
if (header.hash.length !== 64) {
|
|
313
|
+
throw new Error('Header hash must be 32 hex bytes.')
|
|
314
|
+
}
|
|
315
|
+
if (header.hash !== asString(blockHash(header))) {
|
|
316
|
+
throw new Error('Header hash is invalid.')
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Ensures that a header has a valid proof-of-work
|
|
322
|
+
* Requires chain is 'main'
|
|
323
|
+
*
|
|
324
|
+
* @param header The header to validate
|
|
325
|
+
*
|
|
326
|
+
* @returns true if the header is valid
|
|
327
|
+
*/
|
|
328
|
+
export function validateHeaderDifficulty(hash: Buffer, bits: number) {
|
|
329
|
+
const hashBN = new BigNumber(asArray(hash))
|
|
330
|
+
|
|
331
|
+
const target = convertBitsToTarget(bits)
|
|
332
|
+
|
|
333
|
+
if (hashBN.lte(target)) return true
|
|
334
|
+
|
|
335
|
+
throw new Error('Block hash is not less than specified target.')
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Computes double sha256 hash of bitcoin block header
|
|
340
|
+
* bytes are reversed to bigendian order
|
|
341
|
+
*
|
|
342
|
+
* If header is a Buffer, it is required to 80 bytes long
|
|
343
|
+
* and in standard block header serialized encoding.
|
|
344
|
+
*
|
|
345
|
+
* @returns doule sha256 hash of header bytes reversed
|
|
346
|
+
* @publicbody
|
|
347
|
+
*/
|
|
348
|
+
export function blockHash(header: BaseBlockHeader | number[]): string {
|
|
349
|
+
const a = !Array.isArray(header) ? serializeBlockHeader(header) : header
|
|
350
|
+
if (a.length !== 80) throw new Error('Block header must be 80 bytes long.')
|
|
351
|
+
return asString(doubleSha256BE(a))
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Serializes a block header as an 80 byte Buffer.
|
|
356
|
+
* The exact serialized format is defined in the Bitcoin White Paper
|
|
357
|
+
* such that computing a double sha256 hash of the buffer computes
|
|
358
|
+
* the block hash for the header.
|
|
359
|
+
* @returns 80 byte Buffer
|
|
360
|
+
* @publicbody
|
|
361
|
+
*/
|
|
362
|
+
export function serializeBlockHeader(header: BaseBlockHeader, buffer?: number[], offset?: number): number[] {
|
|
363
|
+
const writer = new Utils.Writer()
|
|
364
|
+
writer.writeUInt32LE(header.version)
|
|
365
|
+
writer.write(asArray(header.previousHash).reverse())
|
|
366
|
+
writer.write(asArray(header.merkleRoot).reverse())
|
|
367
|
+
writer.writeUInt32LE(header.time)
|
|
368
|
+
writer.writeUInt32LE(header.bits)
|
|
369
|
+
writer.writeUInt32LE(header.nonce)
|
|
370
|
+
const data = writer.toArray()
|
|
371
|
+
if (buffer) {
|
|
372
|
+
offset ||= 0
|
|
373
|
+
buffer.splice(offset, buffer.length, ...data)
|
|
374
|
+
}
|
|
375
|
+
return data
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Deserialize a block header from an 80 byte buffer
|
|
380
|
+
* @publicbody
|
|
381
|
+
*/
|
|
382
|
+
export function deserializeBlockHeader(buffer: number[], offset = 0): BaseBlockHeader {
|
|
383
|
+
const reader = new Utils.Reader(buffer, offset)
|
|
384
|
+
const header: BaseBlockHeader = {
|
|
385
|
+
version: reader.readUInt32LE(),
|
|
386
|
+
previousHash: asString(reader.read(32).reverse()),
|
|
387
|
+
merkleRoot: asString(reader.read(32).reverse()),
|
|
388
|
+
time: reader.readUInt32LE(),
|
|
389
|
+
bits: reader.readUInt32LE(),
|
|
390
|
+
nonce: reader.readUInt32LE()
|
|
391
|
+
}
|
|
392
|
+
return header
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Returns the genesis block for the specified chain.
|
|
397
|
+
* @publicbody
|
|
398
|
+
*/
|
|
399
|
+
export function genesisHeader(chain: Chain): BlockHeader {
|
|
400
|
+
return chain === 'main'
|
|
401
|
+
? {
|
|
402
|
+
version: 1,
|
|
403
|
+
previousHash: '0000000000000000000000000000000000000000000000000000000000000000',
|
|
404
|
+
merkleRoot: '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b',
|
|
405
|
+
time: 1231006505,
|
|
406
|
+
bits: 486604799,
|
|
407
|
+
nonce: 2083236893,
|
|
408
|
+
height: 0,
|
|
409
|
+
hash: '000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f'
|
|
410
|
+
}
|
|
411
|
+
: {
|
|
412
|
+
version: 1,
|
|
413
|
+
previousHash: '0000000000000000000000000000000000000000000000000000000000000000',
|
|
414
|
+
merkleRoot: '4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b',
|
|
415
|
+
time: 1296688602,
|
|
416
|
+
bits: 486604799,
|
|
417
|
+
nonce: 414098458,
|
|
418
|
+
height: 0,
|
|
419
|
+
hash: '000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943'
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Returns the genesis block for the specified chain.
|
|
425
|
+
* @publicbody
|
|
426
|
+
*/
|
|
427
|
+
export function genesisBuffer(chain: Chain): number[] {
|
|
428
|
+
return serializeBlockHeader(genesisHeader(chain))
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Returns a copy of a Buffer with byte order reversed.
|
|
433
|
+
* @returns new buffer with byte order reversed.
|
|
434
|
+
* @publicbody
|
|
435
|
+
*/
|
|
436
|
+
export function swapByteOrder(buffer: number[]): number[] {
|
|
437
|
+
return buffer.slice().reverse()
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* @param num a number value in the Uint32 value range
|
|
442
|
+
* @param littleEndian true for little-endian byte order in Buffer
|
|
443
|
+
* @returns four byte buffer with Uint32 number encoded
|
|
444
|
+
* @publicbody
|
|
445
|
+
*/
|
|
446
|
+
export function convertUint32ToBuffer(n: number, littleEndian = true): number[] {
|
|
447
|
+
const a = [
|
|
448
|
+
n & 0xff, // lowest byte
|
|
449
|
+
(n >> 8) & 0xff,
|
|
450
|
+
(n >> 16) & 0xff,
|
|
451
|
+
(n >> 24) & 0xff // highest byte
|
|
452
|
+
]
|
|
453
|
+
return littleEndian ? a : a.reverse()
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
export function writeUInt32LE(n: number, a: number[], offset: number): number {
|
|
457
|
+
a[offset++] = n & 0xff // lowest byte
|
|
458
|
+
a[offset++] = (n >> 8) & 0xff
|
|
459
|
+
a[offset++] = (n >> 16) & 0xff
|
|
460
|
+
a[offset++] = (n >> 24) & 0xff // highest byte
|
|
461
|
+
return offset
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
export function writeUInt32BE(n: number, a: number[], offset: number): number {
|
|
465
|
+
a[offset++] = (n >> 24) & 0xff // highest byte
|
|
466
|
+
a[offset++] = (n >> 16) & 0xff
|
|
467
|
+
a[offset++] = (n >> 8) & 0xff
|
|
468
|
+
a[offset++] = n & 0xff // lowest byte
|
|
469
|
+
return offset
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
export function readUInt32LE(a: number[], offset: number): number {
|
|
473
|
+
return a[offset++] | (a[offset++] << 8) | (a[offset++] << 16) | (a[offset++] << 24)
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
export function readUInt32BE(a: number[], offset: number): number {
|
|
477
|
+
return (a[offset++] << 24) | (a[offset++] << 16) | (a[offset++] << 8) | a[offset++]
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* @param buffer four byte buffer with Uint32 number encoded
|
|
482
|
+
* @param littleEndian true for little-endian byte order in Buffer
|
|
483
|
+
* @returns a number value in the Uint32 value range
|
|
484
|
+
* @publicbody
|
|
485
|
+
*/
|
|
486
|
+
export function convertBufferToUint32(buffer: number[], littleEndian = true): number {
|
|
487
|
+
const a = littleEndian ? buffer : buffer.slice().reverse()
|
|
488
|
+
const n = a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24)
|
|
489
|
+
return n
|
|
490
|
+
}
|