@atomiqlabs/chain-starknet 4.0.0-dev.12 → 4.0.0-dev.13

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.
Files changed (146) hide show
  1. package/LICENSE +201 -201
  2. package/dist/index.d.ts +38 -38
  3. package/dist/index.js +54 -54
  4. package/dist/starknet/StarknetChainType.d.ts +13 -13
  5. package/dist/starknet/StarknetChainType.js +2 -2
  6. package/dist/starknet/StarknetInitializer.d.ts +27 -27
  7. package/dist/starknet/StarknetInitializer.js +69 -69
  8. package/dist/starknet/btcrelay/BtcRelayAbi.d.ts +250 -250
  9. package/dist/starknet/btcrelay/BtcRelayAbi.js +341 -341
  10. package/dist/starknet/btcrelay/StarknetBtcRelay.d.ts +186 -186
  11. package/dist/starknet/btcrelay/StarknetBtcRelay.js +379 -379
  12. package/dist/starknet/btcrelay/headers/StarknetBtcHeader.d.ts +31 -31
  13. package/dist/starknet/btcrelay/headers/StarknetBtcHeader.js +74 -74
  14. package/dist/starknet/btcrelay/headers/StarknetBtcStoredHeader.d.ts +51 -51
  15. package/dist/starknet/btcrelay/headers/StarknetBtcStoredHeader.js +113 -113
  16. package/dist/starknet/chain/StarknetAction.d.ts +19 -19
  17. package/dist/starknet/chain/StarknetAction.js +73 -73
  18. package/dist/starknet/chain/StarknetChainInterface.d.ts +52 -52
  19. package/dist/starknet/chain/StarknetChainInterface.js +91 -91
  20. package/dist/starknet/chain/StarknetModule.d.ts +14 -14
  21. package/dist/starknet/chain/StarknetModule.js +13 -13
  22. package/dist/starknet/chain/modules/ERC20Abi.d.ts +755 -755
  23. package/dist/starknet/chain/modules/ERC20Abi.js +1032 -1032
  24. package/dist/starknet/chain/modules/StarknetAccounts.d.ts +6 -6
  25. package/dist/starknet/chain/modules/StarknetAccounts.js +24 -24
  26. package/dist/starknet/chain/modules/StarknetAddresses.d.ts +9 -9
  27. package/dist/starknet/chain/modules/StarknetAddresses.js +26 -26
  28. package/dist/starknet/chain/modules/StarknetBlocks.d.ts +20 -20
  29. package/dist/starknet/chain/modules/StarknetBlocks.js +64 -64
  30. package/dist/starknet/chain/modules/StarknetEvents.d.ts +44 -44
  31. package/dist/starknet/chain/modules/StarknetEvents.js +88 -88
  32. package/dist/starknet/chain/modules/StarknetFees.d.ts +77 -77
  33. package/dist/starknet/chain/modules/StarknetFees.js +114 -114
  34. package/dist/starknet/chain/modules/StarknetSignatures.d.ts +29 -29
  35. package/dist/starknet/chain/modules/StarknetSignatures.js +72 -72
  36. package/dist/starknet/chain/modules/StarknetTokens.d.ts +69 -69
  37. package/dist/starknet/chain/modules/StarknetTokens.js +102 -98
  38. package/dist/starknet/chain/modules/StarknetTransactions.d.ts +93 -93
  39. package/dist/starknet/chain/modules/StarknetTransactions.js +261 -260
  40. package/dist/starknet/contract/StarknetContractBase.d.ts +13 -13
  41. package/dist/starknet/contract/StarknetContractBase.js +20 -16
  42. package/dist/starknet/contract/StarknetContractModule.d.ts +8 -8
  43. package/dist/starknet/contract/StarknetContractModule.js +11 -11
  44. package/dist/starknet/contract/modules/StarknetContractEvents.d.ts +51 -51
  45. package/dist/starknet/contract/modules/StarknetContractEvents.js +97 -97
  46. package/dist/starknet/events/StarknetChainEvents.d.ts +21 -21
  47. package/dist/starknet/events/StarknetChainEvents.js +52 -52
  48. package/dist/starknet/events/StarknetChainEventsBrowser.d.ts +89 -90
  49. package/dist/starknet/events/StarknetChainEventsBrowser.js +296 -294
  50. package/dist/starknet/provider/RpcProviderWithRetries.d.ts +21 -21
  51. package/dist/starknet/provider/RpcProviderWithRetries.js +32 -32
  52. package/dist/starknet/spv_swap/SpvVaultContractAbi.d.ts +488 -488
  53. package/dist/starknet/spv_swap/SpvVaultContractAbi.js +656 -656
  54. package/dist/starknet/spv_swap/StarknetSpvVaultContract.d.ts +66 -66
  55. package/dist/starknet/spv_swap/StarknetSpvVaultContract.js +382 -382
  56. package/dist/starknet/spv_swap/StarknetSpvVaultData.d.ts +49 -49
  57. package/dist/starknet/spv_swap/StarknetSpvVaultData.js +145 -145
  58. package/dist/starknet/spv_swap/StarknetSpvWithdrawalData.d.ts +25 -25
  59. package/dist/starknet/spv_swap/StarknetSpvWithdrawalData.js +72 -72
  60. package/dist/starknet/swaps/EscrowManagerAbi.d.ts +431 -431
  61. package/dist/starknet/swaps/EscrowManagerAbi.js +583 -583
  62. package/dist/starknet/swaps/StarknetSwapContract.d.ts +191 -191
  63. package/dist/starknet/swaps/StarknetSwapContract.js +424 -424
  64. package/dist/starknet/swaps/StarknetSwapData.d.ts +74 -74
  65. package/dist/starknet/swaps/StarknetSwapData.js +325 -325
  66. package/dist/starknet/swaps/StarknetSwapModule.d.ts +10 -10
  67. package/dist/starknet/swaps/StarknetSwapModule.js +11 -11
  68. package/dist/starknet/swaps/handlers/IHandler.d.ts +13 -13
  69. package/dist/starknet/swaps/handlers/IHandler.js +2 -2
  70. package/dist/starknet/swaps/handlers/claim/ClaimHandlers.d.ts +13 -13
  71. package/dist/starknet/swaps/handlers/claim/ClaimHandlers.js +13 -13
  72. package/dist/starknet/swaps/handlers/claim/HashlockClaimHandler.d.ts +21 -21
  73. package/dist/starknet/swaps/handlers/claim/HashlockClaimHandler.js +44 -44
  74. package/dist/starknet/swaps/handlers/claim/btc/BitcoinNoncedOutputClaimHandler.d.ts +24 -24
  75. package/dist/starknet/swaps/handlers/claim/btc/BitcoinNoncedOutputClaimHandler.js +48 -48
  76. package/dist/starknet/swaps/handlers/claim/btc/BitcoinOutputClaimHandler.d.ts +25 -25
  77. package/dist/starknet/swaps/handlers/claim/btc/BitcoinOutputClaimHandler.js +40 -40
  78. package/dist/starknet/swaps/handlers/claim/btc/BitcoinTxIdClaimHandler.d.ts +20 -20
  79. package/dist/starknet/swaps/handlers/claim/btc/BitcoinTxIdClaimHandler.js +30 -30
  80. package/dist/starknet/swaps/handlers/claim/btc/IBitcoinClaimHandler.d.ts +45 -45
  81. package/dist/starknet/swaps/handlers/claim/btc/IBitcoinClaimHandler.js +52 -52
  82. package/dist/starknet/swaps/handlers/refund/TimelockRefundHandler.d.ts +17 -17
  83. package/dist/starknet/swaps/handlers/refund/TimelockRefundHandler.js +27 -27
  84. package/dist/starknet/swaps/modules/StarknetLpVault.d.ts +69 -69
  85. package/dist/starknet/swaps/modules/StarknetLpVault.js +122 -122
  86. package/dist/starknet/swaps/modules/StarknetSwapClaim.d.ts +53 -53
  87. package/dist/starknet/swaps/modules/StarknetSwapClaim.js +100 -100
  88. package/dist/starknet/swaps/modules/StarknetSwapInit.d.ts +94 -87
  89. package/dist/starknet/swaps/modules/StarknetSwapInit.js +235 -225
  90. package/dist/starknet/swaps/modules/StarknetSwapRefund.d.ts +62 -62
  91. package/dist/starknet/swaps/modules/StarknetSwapRefund.js +128 -128
  92. package/dist/starknet/wallet/StarknetKeypairWallet.d.ts +7 -7
  93. package/dist/starknet/wallet/StarknetKeypairWallet.js +35 -30
  94. package/dist/starknet/wallet/StarknetSigner.d.ts +12 -12
  95. package/dist/starknet/wallet/StarknetSigner.js +47 -46
  96. package/dist/utils/Utils.d.ts +37 -37
  97. package/dist/utils/Utils.js +260 -261
  98. package/package.json +43 -37
  99. package/src/index.ts +47 -47
  100. package/src/starknet/StarknetChainType.ts +28 -28
  101. package/src/starknet/StarknetInitializer.ts +108 -108
  102. package/src/starknet/btcrelay/BtcRelayAbi.ts +338 -338
  103. package/src/starknet/btcrelay/StarknetBtcRelay.ts +494 -494
  104. package/src/starknet/btcrelay/headers/StarknetBtcHeader.ts +100 -100
  105. package/src/starknet/btcrelay/headers/StarknetBtcStoredHeader.ts +141 -141
  106. package/src/starknet/chain/StarknetAction.ts +85 -85
  107. package/src/starknet/chain/StarknetChainInterface.ts +149 -149
  108. package/src/starknet/chain/StarknetModule.ts +19 -19
  109. package/src/starknet/chain/modules/ERC20Abi.ts +1029 -1029
  110. package/src/starknet/chain/modules/StarknetAccounts.ts +25 -25
  111. package/src/starknet/chain/modules/StarknetAddresses.ts +22 -22
  112. package/src/starknet/chain/modules/StarknetBlocks.ts +75 -74
  113. package/src/starknet/chain/modules/StarknetEvents.ts +104 -104
  114. package/src/starknet/chain/modules/StarknetFees.ts +154 -154
  115. package/src/starknet/chain/modules/StarknetSignatures.ts +91 -91
  116. package/src/starknet/chain/modules/StarknetTokens.ts +120 -116
  117. package/src/starknet/chain/modules/StarknetTransactions.ts +285 -283
  118. package/src/starknet/contract/StarknetContractBase.ts +30 -26
  119. package/src/starknet/contract/StarknetContractModule.ts +16 -16
  120. package/src/starknet/contract/modules/StarknetContractEvents.ts +134 -134
  121. package/src/starknet/events/StarknetChainEvents.ts +67 -67
  122. package/src/starknet/events/StarknetChainEventsBrowser.ts +411 -411
  123. package/src/starknet/provider/RpcProviderWithRetries.ts +43 -43
  124. package/src/starknet/spv_swap/SpvVaultContractAbi.ts +656 -656
  125. package/src/starknet/spv_swap/StarknetSpvVaultContract.ts +483 -483
  126. package/src/starknet/spv_swap/StarknetSpvVaultData.ts +195 -195
  127. package/src/starknet/spv_swap/StarknetSpvWithdrawalData.ts +79 -79
  128. package/src/starknet/swaps/EscrowManagerAbi.ts +582 -582
  129. package/src/starknet/swaps/StarknetSwapContract.ts +647 -647
  130. package/src/starknet/swaps/StarknetSwapData.ts +455 -455
  131. package/src/starknet/swaps/StarknetSwapModule.ts +17 -17
  132. package/src/starknet/swaps/handlers/IHandler.ts +20 -20
  133. package/src/starknet/swaps/handlers/claim/ClaimHandlers.ts +23 -23
  134. package/src/starknet/swaps/handlers/claim/HashlockClaimHandler.ts +53 -53
  135. package/src/starknet/swaps/handlers/claim/btc/BitcoinNoncedOutputClaimHandler.ts +73 -73
  136. package/src/starknet/swaps/handlers/claim/btc/BitcoinOutputClaimHandler.ts +67 -67
  137. package/src/starknet/swaps/handlers/claim/btc/BitcoinTxIdClaimHandler.ts +50 -50
  138. package/src/starknet/swaps/handlers/claim/btc/IBitcoinClaimHandler.ts +102 -102
  139. package/src/starknet/swaps/handlers/refund/TimelockRefundHandler.ts +38 -38
  140. package/src/starknet/swaps/modules/StarknetLpVault.ts +147 -147
  141. package/src/starknet/swaps/modules/StarknetSwapClaim.ts +141 -141
  142. package/src/starknet/swaps/modules/StarknetSwapInit.ts +300 -287
  143. package/src/starknet/swaps/modules/StarknetSwapRefund.ts +196 -196
  144. package/src/starknet/wallet/StarknetKeypairWallet.ts +44 -39
  145. package/src/starknet/wallet/StarknetSigner.ts +55 -55
  146. package/src/utils/Utils.ts +251 -252
@@ -1,379 +1,379 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.StarknetBtcRelay = void 0;
4
- const buffer_1 = require("buffer");
5
- const StarknetBtcHeader_1 = require("./headers/StarknetBtcHeader");
6
- const base_1 = require("@atomiqlabs/base");
7
- const Utils_1 = require("../../utils/Utils");
8
- const StarknetContractBase_1 = require("../contract/StarknetContractBase");
9
- const StarknetBtcStoredHeader_1 = require("./headers/StarknetBtcStoredHeader");
10
- const BtcRelayAbi_1 = require("./BtcRelayAbi");
11
- const starknet_1 = require("starknet");
12
- const StarknetFees_1 = require("../chain/modules/StarknetFees");
13
- const StarknetAction_1 = require("../chain/StarknetAction");
14
- function serializeBlockHeader(e) {
15
- return new StarknetBtcHeader_1.StarknetBtcHeader({
16
- reversed_version: (0, Utils_1.u32ReverseEndianness)(e.getVersion()),
17
- previous_blockhash: (0, Utils_1.bufferToU32Array)(buffer_1.Buffer.from(e.getPrevBlockhash(), "hex").reverse()),
18
- merkle_root: (0, Utils_1.bufferToU32Array)(buffer_1.Buffer.from(e.getMerkleRoot(), "hex").reverse()),
19
- reversed_timestamp: (0, Utils_1.u32ReverseEndianness)(e.getTimestamp()),
20
- nbits: (0, Utils_1.u32ReverseEndianness)(e.getNbits()),
21
- nonce: (0, Utils_1.u32ReverseEndianness)(e.getNonce()),
22
- hash: buffer_1.Buffer.from(e.getHash(), "hex").reverse()
23
- });
24
- }
25
- const GAS_PER_BLOCKHEADER = { l1DataGas: 600, l2Gas: 40000000, l1Gas: 0 };
26
- const GAS_PER_BLOCKHEADER_FORK = { l1DataGas: 1000, l2Gas: 60000000, l1Gas: 0 };
27
- const btcRelayAddreses = {
28
- [base_1.BitcoinNetwork.TESTNET4]: "0x0099b63f39f0cabb767361de3d8d3e97212351a51540e2687c2571f4da490dbe",
29
- [base_1.BitcoinNetwork.TESTNET]: "0x068601c79da2231d21e015ccfd59c243861156fa523a12c9f987ec28eb8dbc8c",
30
- [base_1.BitcoinNetwork.MAINNET]: "0x057b14a4231b82f1e525ff35a722d893ca3dd2bde0baa6cee97937c5be861dbc"
31
- };
32
- function serializeCalldata(headers, storedHeader, span) {
33
- span.push((0, Utils_1.toHex)(headers.length));
34
- headers.forEach(header => {
35
- span.push(...header.serialize());
36
- });
37
- span.push(...storedHeader.serialize());
38
- return span;
39
- }
40
- const logger = (0, Utils_1.getLogger)("StarknetBtcRelay: ");
41
- class StarknetBtcRelay extends StarknetContractBase_1.StarknetContractBase {
42
- SaveMainHeaders(signer, mainHeaders, storedHeader) {
43
- return new StarknetAction_1.StarknetAction(signer, this.Chain, {
44
- contractAddress: this.contract.address,
45
- entrypoint: "submit_main_blockheaders",
46
- calldata: serializeCalldata(mainHeaders, storedHeader, [])
47
- }, (0, StarknetFees_1.starknetGasMul)(GAS_PER_BLOCKHEADER, mainHeaders.length));
48
- }
49
- SaveShortForkHeaders(signer, forkHeaders, storedHeader) {
50
- return new StarknetAction_1.StarknetAction(signer, this.Chain, {
51
- contractAddress: this.contract.address,
52
- entrypoint: "submit_short_fork_blockheaders",
53
- calldata: serializeCalldata(forkHeaders, storedHeader, [])
54
- }, (0, StarknetFees_1.starknetGasMul)(GAS_PER_BLOCKHEADER, forkHeaders.length));
55
- }
56
- SaveLongForkHeaders(signer, forkId, forkHeaders, storedHeader, totalForkHeaders = 100) {
57
- return new StarknetAction_1.StarknetAction(signer, this.Chain, {
58
- contractAddress: this.contract.address,
59
- entrypoint: "submit_fork_blockheaders",
60
- calldata: serializeCalldata(forkHeaders, storedHeader, [(0, Utils_1.toHex)(forkId)])
61
- }, (0, StarknetFees_1.starknetGasAdd)((0, StarknetFees_1.starknetGasMul)(GAS_PER_BLOCKHEADER, forkHeaders.length), (0, StarknetFees_1.starknetGasMul)(GAS_PER_BLOCKHEADER_FORK, totalForkHeaders)));
62
- }
63
- constructor(chainInterface, bitcoinRpc, bitcoinNetwork, contractAddress = btcRelayAddreses[bitcoinNetwork]) {
64
- super(chainInterface, contractAddress, BtcRelayAbi_1.BtcRelayAbi);
65
- this.maxHeadersPerTx = 100;
66
- this.maxForkHeadersPerTx = 100;
67
- this.maxShortForkHeadersPerTx = 100;
68
- this.bitcoinRpc = bitcoinRpc;
69
- }
70
- /**
71
- * Computes subsequent commited headers as they will appear on the blockchain when transactions
72
- * are submitted & confirmed
73
- *
74
- * @param initialStoredHeader
75
- * @param syncedHeaders
76
- * @private
77
- */
78
- computeCommitedHeaders(initialStoredHeader, syncedHeaders) {
79
- const computedCommitedHeaders = [initialStoredHeader];
80
- for (let blockHeader of syncedHeaders) {
81
- computedCommitedHeaders.push(computedCommitedHeaders[computedCommitedHeaders.length - 1].computeNext(blockHeader));
82
- }
83
- return computedCommitedHeaders;
84
- }
85
- /**
86
- * A common logic for submitting blockheaders in a transaction
87
- *
88
- * @param signer
89
- * @param headers headers to sync to the btc relay
90
- * @param storedHeader current latest stored block header for a given fork
91
- * @param tipWork work of the current tip in a given fork
92
- * @param forkId forkId to submit to, forkId=0 means main chain, forkId=-1 means short fork
93
- * @param feeRate feeRate for the transaction
94
- * @private
95
- */
96
- async _saveHeaders(signer, headers, storedHeader, tipWork, forkId, feeRate) {
97
- const blockHeaderObj = headers.map(serializeBlockHeader);
98
- let starknetAction;
99
- switch (forkId) {
100
- case -1:
101
- starknetAction = this.SaveShortForkHeaders(signer, blockHeaderObj, storedHeader);
102
- break;
103
- case 0:
104
- starknetAction = this.SaveMainHeaders(signer, blockHeaderObj, storedHeader);
105
- break;
106
- default:
107
- starknetAction = this.SaveLongForkHeaders(signer, forkId, blockHeaderObj, storedHeader);
108
- break;
109
- }
110
- const tx = await starknetAction.tx(feeRate);
111
- const computedCommitedHeaders = this.computeCommitedHeaders(storedHeader, blockHeaderObj);
112
- const lastStoredHeader = computedCommitedHeaders[computedCommitedHeaders.length - 1];
113
- if (forkId !== 0 && base_1.StatePredictorUtils.gtBuffer(lastStoredHeader.getBlockHash(), tipWork)) {
114
- //Fork's work is higher than main chain's work, this fork will become a main chain
115
- forkId = 0;
116
- }
117
- return {
118
- forkId: forkId,
119
- lastStoredHeader,
120
- tx,
121
- computedCommitedHeaders
122
- };
123
- }
124
- getBlock(commitHash, blockHash) {
125
- const keys = [commitHash == null ? null : (0, Utils_1.toHex)(commitHash)];
126
- if (blockHash != null) {
127
- const starknetBlockHash = starknet_1.hash.computePoseidonHashOnElements((0, Utils_1.bufferToU32Array)(buffer_1.Buffer.from([...blockHash]).reverse()));
128
- keys.push(starknetBlockHash);
129
- }
130
- return this.Events.findInContractEvents(["btc_relay::events::StoreHeader", "btc_relay::events::StoreForkHeader"], keys, (event) => {
131
- return Promise.resolve([StarknetBtcStoredHeader_1.StarknetBtcStoredHeader.fromSerializedFeltArray(event.data), BigInt(event.params.commit_hash)]);
132
- });
133
- }
134
- async getBlockHeight() {
135
- return Number(await this.contract.get_blockheight());
136
- }
137
- /**
138
- * Returns data about current main chain tip stored in the btc relay
139
- */
140
- async getTipData() {
141
- const commitHash = await this.contract.get_tip_commit_hash();
142
- if (commitHash == null || BigInt(commitHash) === BigInt(0))
143
- return null;
144
- const result = await this.getBlock(commitHash);
145
- if (result == null)
146
- return null;
147
- const [storedBlockHeader] = result;
148
- return {
149
- blockheight: storedBlockHeader.getBlockheight(),
150
- commitHash: (0, Utils_1.bigNumberishToBuffer)(commitHash, 32).toString("hex"),
151
- blockhash: storedBlockHeader.getBlockHash().toString("hex"),
152
- chainWork: storedBlockHeader.getChainWork()
153
- };
154
- }
155
- /**
156
- * Retrieves blockheader with a specific blockhash, returns null if requiredBlockheight is provided and
157
- * btc relay contract is not synced up to the desired blockheight
158
- *
159
- * @param blockData
160
- * @param requiredBlockheight
161
- */
162
- async retrieveLogAndBlockheight(blockData, requiredBlockheight) {
163
- //TODO: we can fetch the blockheight and events in parallel
164
- const blockHeight = await this.getBlockHeight();
165
- if (requiredBlockheight != null && blockHeight < requiredBlockheight) {
166
- return null;
167
- }
168
- const result = await this.getBlock(null, buffer_1.Buffer.from(blockData.blockhash, "hex"));
169
- if (result == null)
170
- return null;
171
- const [storedBlockHeader, commitHash] = result;
172
- //Check if block is part of the main chain
173
- const chainCommitment = await this.contract.get_commit_hash(storedBlockHeader.block_height);
174
- if (BigInt(chainCommitment) !== BigInt(commitHash))
175
- return null;
176
- logger.debug("retrieveLogAndBlockheight(): block found," +
177
- " commit hash: " + (0, Utils_1.toHex)(commitHash) + " blockhash: " + blockData.blockhash + " current btc relay height: " + blockHeight);
178
- return { header: storedBlockHeader, height: blockHeight };
179
- }
180
- /**
181
- * Retrieves blockheader data by blockheader's commit hash,
182
- *
183
- * @param commitmentHashStr
184
- * @param blockData
185
- */
186
- async retrieveLogByCommitHash(commitmentHashStr, blockData) {
187
- const result = await this.getBlock(commitmentHashStr, buffer_1.Buffer.from(blockData.blockhash, "hex"));
188
- if (result == null)
189
- return null;
190
- const [storedBlockHeader, commitHash] = result;
191
- //Check if block is part of the main chain
192
- const chainCommitment = await this.contract.get_commit_hash(storedBlockHeader.block_height);
193
- if (BigInt(chainCommitment) !== BigInt(commitHash))
194
- return null;
195
- logger.debug("retrieveLogByCommitHash(): block found," +
196
- " commit hash: " + commitmentHashStr + " blockhash: " + blockData.blockhash + " height: " + storedBlockHeader.block_height);
197
- return storedBlockHeader;
198
- }
199
- /**
200
- * Retrieves latest known stored blockheader & blockheader from bitcoin RPC that is in the main chain
201
- */
202
- async retrieveLatestKnownBlockLog() {
203
- const data = await this.Events.findInContractEvents(["btc_relay::events::StoreHeader", "btc_relay::events::StoreForkHeader"], null, async (event) => {
204
- const storedHeader = StarknetBtcStoredHeader_1.StarknetBtcStoredHeader.fromSerializedFeltArray(event.data);
205
- const blockHashHex = storedHeader.getBlockHash().toString("hex");
206
- const commitHash = event.params.commit_hash;
207
- const [isInBtcMainChain, btcRelayCommitHash] = await Promise.all([
208
- this.bitcoinRpc.isInMainChain(blockHashHex).catch(() => false),
209
- this.contract.get_commit_hash(storedHeader.block_height)
210
- ]);
211
- if (!isInBtcMainChain)
212
- return null;
213
- if (BigInt(commitHash) !== BigInt(btcRelayCommitHash))
214
- return null;
215
- return {
216
- resultStoredHeader: storedHeader,
217
- resultBitcoinHeader: await this.bitcoinRpc.getBlockHeader(blockHashHex),
218
- commitHash: commitHash
219
- };
220
- });
221
- if (data != null)
222
- logger.debug("retrieveLatestKnownBlockLog(): block found," +
223
- " commit hash: " + (0, Utils_1.toHex)(data.commitHash) + " blockhash: " + data.resultBitcoinHeader.getHash() +
224
- " height: " + data.resultStoredHeader.getBlockheight());
225
- return data;
226
- }
227
- /**
228
- * Saves blockheaders as a bitcoin main chain to the btc relay
229
- *
230
- * @param signer
231
- * @param mainHeaders
232
- * @param storedHeader
233
- * @param feeRate
234
- */
235
- saveMainHeaders(signer, mainHeaders, storedHeader, feeRate) {
236
- logger.debug("saveMainHeaders(): submitting main blockheaders, count: " + mainHeaders.length);
237
- return this._saveHeaders(signer, mainHeaders, storedHeader, null, 0, feeRate);
238
- }
239
- /**
240
- * Creates a new long fork and submits the headers to it
241
- *
242
- * @param signer
243
- * @param forkHeaders
244
- * @param storedHeader
245
- * @param tipWork
246
- * @param feeRate
247
- */
248
- async saveNewForkHeaders(signer, forkHeaders, storedHeader, tipWork, feeRate) {
249
- let forkId = Math.floor(Math.random() * 0xFFFFFFFFFFFF);
250
- logger.debug("saveNewForkHeaders(): submitting new fork & blockheaders," +
251
- " count: " + forkHeaders.length + " forkId: 0x" + forkId.toString(16));
252
- return await this._saveHeaders(signer, forkHeaders, storedHeader, tipWork, forkId, feeRate);
253
- }
254
- /**
255
- * Continues submitting blockheaders to a given fork
256
- *
257
- * @param signer
258
- * @param forkHeaders
259
- * @param storedHeader
260
- * @param forkId
261
- * @param tipWork
262
- * @param feeRate
263
- */
264
- saveForkHeaders(signer, forkHeaders, storedHeader, forkId, tipWork, feeRate) {
265
- logger.debug("saveForkHeaders(): submitting blockheaders to existing fork," +
266
- " count: " + forkHeaders.length + " forkId: 0x" + forkId.toString(16));
267
- return this._saveHeaders(signer, forkHeaders, storedHeader, tipWork, forkId, feeRate);
268
- }
269
- /**
270
- * Submits short fork with given blockheaders
271
- *
272
- * @param signer
273
- * @param forkHeaders
274
- * @param storedHeader
275
- * @param tipWork
276
- * @param feeRate
277
- */
278
- saveShortForkHeaders(signer, forkHeaders, storedHeader, tipWork, feeRate) {
279
- logger.debug("saveShortForkHeaders(): submitting short fork blockheaders," +
280
- " count: " + forkHeaders.length);
281
- return this._saveHeaders(signer, forkHeaders, storedHeader, tipWork, -1, feeRate);
282
- }
283
- /**
284
- * Estimate required synchronization fee (worst case) to synchronize btc relay to the required blockheight
285
- *
286
- * @param requiredBlockheight
287
- * @param feeRate
288
- */
289
- async estimateSynchronizeFee(requiredBlockheight, feeRate) {
290
- const tipData = await this.getTipData();
291
- const currBlockheight = tipData.blockheight;
292
- const blockheightDelta = requiredBlockheight - currBlockheight;
293
- if (blockheightDelta <= 0)
294
- return 0n;
295
- const synchronizationFee = BigInt(blockheightDelta) * await this.getFeePerBlock(feeRate);
296
- logger.debug("estimateSynchronizeFee(): required blockheight: " + requiredBlockheight +
297
- " blockheight delta: " + blockheightDelta + " fee: " + synchronizationFee.toString(10));
298
- return synchronizationFee;
299
- }
300
- /**
301
- * Returns fee required (in SOL) to synchronize a single block to btc relay
302
- *
303
- * @param feeRate
304
- */
305
- async getFeePerBlock(feeRate) {
306
- feeRate ?? (feeRate = await this.Chain.Fees.getFeeRate());
307
- return StarknetFees_1.StarknetFees.getGasFee(GAS_PER_BLOCKHEADER, feeRate);
308
- }
309
- /**
310
- * Gets fee rate required for submitting blockheaders to the main chain
311
- */
312
- getMainFeeRate(signer) {
313
- return this.Chain.Fees.getFeeRate();
314
- }
315
- /**
316
- * Gets fee rate required for submitting blockheaders to the specific fork
317
- */
318
- getForkFeeRate(signer, forkId) {
319
- return this.Chain.Fees.getFeeRate();
320
- }
321
- saveInitialHeader(signer, header, epochStart, pastBlocksTimestamps, feeRate) {
322
- throw new Error("Not supported, starknet contract is initialized with constructor!");
323
- }
324
- /**
325
- * Gets committed header, identified by blockhash & blockheight, determines required BTC relay blockheight based on
326
- * requiredConfirmations
327
- * If synchronizer is passed & blockhash is not found, it produces transactions to sync up the btc relay to the
328
- * current chain tip & adds them to the txs array
329
- *
330
- * @param signer
331
- * @param btcRelay
332
- * @param btcTxs
333
- * @param txs solana transaction array, in case we need to synchronize the btc relay ourselves the synchronization
334
- * txns are added here
335
- * @param synchronizer optional synchronizer to use to synchronize the btc relay in case it is not yet synchronized
336
- * to the required blockheight
337
- * @param feeRate Fee rate to use for synchronization transactions
338
- * @private
339
- */
340
- static async getCommitedHeadersAndSynchronize(signer, btcRelay, btcTxs, txs, synchronizer, feeRate) {
341
- const leavesTxs = [];
342
- const blockheaders = {};
343
- for (let btcTx of btcTxs) {
344
- const requiredBlockheight = btcTx.blockheight + btcTx.requiredConfirmations - 1;
345
- const result = await (0, Utils_1.tryWithRetries)(() => btcRelay.retrieveLogAndBlockheight({
346
- blockhash: btcTx.blockhash
347
- }, requiredBlockheight));
348
- if (result != null) {
349
- blockheaders[result.header.getBlockHash().toString("hex")] = result.header;
350
- }
351
- else {
352
- leavesTxs.push(btcTx);
353
- }
354
- }
355
- if (leavesTxs.length === 0)
356
- return blockheaders;
357
- //Need to synchronize
358
- if (synchronizer == null)
359
- return null;
360
- //TODO: We don't have to synchronize to tip, only to our required blockheight
361
- const resp = await synchronizer.syncToLatestTxs(signer.toString(), feeRate);
362
- logger.debug("getCommitedHeaderAndSynchronize(): BTC Relay not synchronized to required blockheight, " +
363
- "synchronizing ourselves in " + resp.txs.length + " txs");
364
- logger.debug("getCommitedHeaderAndSynchronize(): BTC Relay computed header map: ", resp.computedHeaderMap);
365
- txs.push(...resp.txs);
366
- for (let key in resp.computedHeaderMap) {
367
- const header = resp.computedHeaderMap[key];
368
- blockheaders[header.getBlockHash().toString("hex")] = header;
369
- }
370
- //Check that blockhashes of all the rest txs are included
371
- for (let btcTx of leavesTxs) {
372
- if (blockheaders[btcTx.blockhash] == null)
373
- return null;
374
- }
375
- //Retrieve computed headers
376
- return blockheaders;
377
- }
378
- }
379
- exports.StarknetBtcRelay = StarknetBtcRelay;
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StarknetBtcRelay = void 0;
4
+ const buffer_1 = require("buffer");
5
+ const StarknetBtcHeader_1 = require("./headers/StarknetBtcHeader");
6
+ const base_1 = require("@atomiqlabs/base");
7
+ const Utils_1 = require("../../utils/Utils");
8
+ const StarknetContractBase_1 = require("../contract/StarknetContractBase");
9
+ const StarknetBtcStoredHeader_1 = require("./headers/StarknetBtcStoredHeader");
10
+ const BtcRelayAbi_1 = require("./BtcRelayAbi");
11
+ const starknet_1 = require("starknet");
12
+ const StarknetFees_1 = require("../chain/modules/StarknetFees");
13
+ const StarknetAction_1 = require("../chain/StarknetAction");
14
+ function serializeBlockHeader(e) {
15
+ return new StarknetBtcHeader_1.StarknetBtcHeader({
16
+ reversed_version: (0, Utils_1.u32ReverseEndianness)(e.getVersion()),
17
+ previous_blockhash: (0, Utils_1.bufferToU32Array)(buffer_1.Buffer.from(e.getPrevBlockhash(), "hex").reverse()),
18
+ merkle_root: (0, Utils_1.bufferToU32Array)(buffer_1.Buffer.from(e.getMerkleRoot(), "hex").reverse()),
19
+ reversed_timestamp: (0, Utils_1.u32ReverseEndianness)(e.getTimestamp()),
20
+ nbits: (0, Utils_1.u32ReverseEndianness)(e.getNbits()),
21
+ nonce: (0, Utils_1.u32ReverseEndianness)(e.getNonce()),
22
+ hash: buffer_1.Buffer.from(e.getHash(), "hex").reverse()
23
+ });
24
+ }
25
+ const GAS_PER_BLOCKHEADER = { l1DataGas: 600, l2Gas: 40000000, l1Gas: 0 };
26
+ const GAS_PER_BLOCKHEADER_FORK = { l1DataGas: 1000, l2Gas: 60000000, l1Gas: 0 };
27
+ const btcRelayAddreses = {
28
+ [base_1.BitcoinNetwork.TESTNET4]: "0x0099b63f39f0cabb767361de3d8d3e97212351a51540e2687c2571f4da490dbe",
29
+ [base_1.BitcoinNetwork.TESTNET]: "0x068601c79da2231d21e015ccfd59c243861156fa523a12c9f987ec28eb8dbc8c",
30
+ [base_1.BitcoinNetwork.MAINNET]: "0x057b14a4231b82f1e525ff35a722d893ca3dd2bde0baa6cee97937c5be861dbc"
31
+ };
32
+ function serializeCalldata(headers, storedHeader, span) {
33
+ span.push((0, Utils_1.toHex)(headers.length));
34
+ headers.forEach(header => {
35
+ span.push(...header.serialize());
36
+ });
37
+ span.push(...storedHeader.serialize());
38
+ return span;
39
+ }
40
+ const logger = (0, Utils_1.getLogger)("StarknetBtcRelay: ");
41
+ class StarknetBtcRelay extends StarknetContractBase_1.StarknetContractBase {
42
+ SaveMainHeaders(signer, mainHeaders, storedHeader) {
43
+ return new StarknetAction_1.StarknetAction(signer, this.Chain, {
44
+ contractAddress: this.contract.address,
45
+ entrypoint: "submit_main_blockheaders",
46
+ calldata: serializeCalldata(mainHeaders, storedHeader, [])
47
+ }, (0, StarknetFees_1.starknetGasMul)(GAS_PER_BLOCKHEADER, mainHeaders.length));
48
+ }
49
+ SaveShortForkHeaders(signer, forkHeaders, storedHeader) {
50
+ return new StarknetAction_1.StarknetAction(signer, this.Chain, {
51
+ contractAddress: this.contract.address,
52
+ entrypoint: "submit_short_fork_blockheaders",
53
+ calldata: serializeCalldata(forkHeaders, storedHeader, [])
54
+ }, (0, StarknetFees_1.starknetGasMul)(GAS_PER_BLOCKHEADER, forkHeaders.length));
55
+ }
56
+ SaveLongForkHeaders(signer, forkId, forkHeaders, storedHeader, totalForkHeaders = 100) {
57
+ return new StarknetAction_1.StarknetAction(signer, this.Chain, {
58
+ contractAddress: this.contract.address,
59
+ entrypoint: "submit_fork_blockheaders",
60
+ calldata: serializeCalldata(forkHeaders, storedHeader, [(0, Utils_1.toHex)(forkId)])
61
+ }, (0, StarknetFees_1.starknetGasAdd)((0, StarknetFees_1.starknetGasMul)(GAS_PER_BLOCKHEADER, forkHeaders.length), (0, StarknetFees_1.starknetGasMul)(GAS_PER_BLOCKHEADER_FORK, totalForkHeaders)));
62
+ }
63
+ constructor(chainInterface, bitcoinRpc, bitcoinNetwork, contractAddress = btcRelayAddreses[bitcoinNetwork]) {
64
+ super(chainInterface, contractAddress, BtcRelayAbi_1.BtcRelayAbi);
65
+ this.maxHeadersPerTx = 100;
66
+ this.maxForkHeadersPerTx = 100;
67
+ this.maxShortForkHeadersPerTx = 100;
68
+ this.bitcoinRpc = bitcoinRpc;
69
+ }
70
+ /**
71
+ * Computes subsequent commited headers as they will appear on the blockchain when transactions
72
+ * are submitted & confirmed
73
+ *
74
+ * @param initialStoredHeader
75
+ * @param syncedHeaders
76
+ * @private
77
+ */
78
+ computeCommitedHeaders(initialStoredHeader, syncedHeaders) {
79
+ const computedCommitedHeaders = [initialStoredHeader];
80
+ for (let blockHeader of syncedHeaders) {
81
+ computedCommitedHeaders.push(computedCommitedHeaders[computedCommitedHeaders.length - 1].computeNext(blockHeader));
82
+ }
83
+ return computedCommitedHeaders;
84
+ }
85
+ /**
86
+ * A common logic for submitting blockheaders in a transaction
87
+ *
88
+ * @param signer
89
+ * @param headers headers to sync to the btc relay
90
+ * @param storedHeader current latest stored block header for a given fork
91
+ * @param tipWork work of the current tip in a given fork
92
+ * @param forkId forkId to submit to, forkId=0 means main chain, forkId=-1 means short fork
93
+ * @param feeRate feeRate for the transaction
94
+ * @private
95
+ */
96
+ async _saveHeaders(signer, headers, storedHeader, tipWork, forkId, feeRate) {
97
+ const blockHeaderObj = headers.map(serializeBlockHeader);
98
+ let starknetAction;
99
+ switch (forkId) {
100
+ case -1:
101
+ starknetAction = this.SaveShortForkHeaders(signer, blockHeaderObj, storedHeader);
102
+ break;
103
+ case 0:
104
+ starknetAction = this.SaveMainHeaders(signer, blockHeaderObj, storedHeader);
105
+ break;
106
+ default:
107
+ starknetAction = this.SaveLongForkHeaders(signer, forkId, blockHeaderObj, storedHeader);
108
+ break;
109
+ }
110
+ const tx = await starknetAction.tx(feeRate);
111
+ const computedCommitedHeaders = this.computeCommitedHeaders(storedHeader, blockHeaderObj);
112
+ const lastStoredHeader = computedCommitedHeaders[computedCommitedHeaders.length - 1];
113
+ if (forkId !== 0 && base_1.StatePredictorUtils.gtBuffer(lastStoredHeader.getBlockHash(), tipWork)) {
114
+ //Fork's work is higher than main chain's work, this fork will become a main chain
115
+ forkId = 0;
116
+ }
117
+ return {
118
+ forkId: forkId,
119
+ lastStoredHeader,
120
+ tx,
121
+ computedCommitedHeaders
122
+ };
123
+ }
124
+ getBlock(commitHash, blockHash) {
125
+ const keys = [commitHash == null ? null : (0, Utils_1.toHex)(commitHash)];
126
+ if (blockHash != null) {
127
+ const starknetBlockHash = starknet_1.hash.computePoseidonHashOnElements((0, Utils_1.bufferToU32Array)(buffer_1.Buffer.from([...blockHash]).reverse()));
128
+ keys.push(starknetBlockHash);
129
+ }
130
+ return this.Events.findInContractEvents(["btc_relay::events::StoreHeader", "btc_relay::events::StoreForkHeader"], keys, (event) => {
131
+ return Promise.resolve([StarknetBtcStoredHeader_1.StarknetBtcStoredHeader.fromSerializedFeltArray(event.data), BigInt(event.params.commit_hash)]);
132
+ });
133
+ }
134
+ async getBlockHeight() {
135
+ return Number(await this.contract.get_blockheight());
136
+ }
137
+ /**
138
+ * Returns data about current main chain tip stored in the btc relay
139
+ */
140
+ async getTipData() {
141
+ const commitHash = await this.contract.get_tip_commit_hash();
142
+ if (commitHash == null || BigInt(commitHash) === BigInt(0))
143
+ return null;
144
+ const result = await this.getBlock(commitHash);
145
+ if (result == null)
146
+ return null;
147
+ const [storedBlockHeader] = result;
148
+ return {
149
+ blockheight: storedBlockHeader.getBlockheight(),
150
+ commitHash: (0, Utils_1.bigNumberishToBuffer)(commitHash, 32).toString("hex"),
151
+ blockhash: storedBlockHeader.getBlockHash().toString("hex"),
152
+ chainWork: storedBlockHeader.getChainWork()
153
+ };
154
+ }
155
+ /**
156
+ * Retrieves blockheader with a specific blockhash, returns null if requiredBlockheight is provided and
157
+ * btc relay contract is not synced up to the desired blockheight
158
+ *
159
+ * @param blockData
160
+ * @param requiredBlockheight
161
+ */
162
+ async retrieveLogAndBlockheight(blockData, requiredBlockheight) {
163
+ //TODO: we can fetch the blockheight and events in parallel
164
+ const blockHeight = await this.getBlockHeight();
165
+ if (requiredBlockheight != null && blockHeight < requiredBlockheight) {
166
+ return null;
167
+ }
168
+ const result = await this.getBlock(null, buffer_1.Buffer.from(blockData.blockhash, "hex"));
169
+ if (result == null)
170
+ return null;
171
+ const [storedBlockHeader, commitHash] = result;
172
+ //Check if block is part of the main chain
173
+ const chainCommitment = await this.contract.get_commit_hash(storedBlockHeader.block_height);
174
+ if (BigInt(chainCommitment) !== BigInt(commitHash))
175
+ return null;
176
+ logger.debug("retrieveLogAndBlockheight(): block found," +
177
+ " commit hash: " + (0, Utils_1.toHex)(commitHash) + " blockhash: " + blockData.blockhash + " current btc relay height: " + blockHeight);
178
+ return { header: storedBlockHeader, height: blockHeight };
179
+ }
180
+ /**
181
+ * Retrieves blockheader data by blockheader's commit hash,
182
+ *
183
+ * @param commitmentHashStr
184
+ * @param blockData
185
+ */
186
+ async retrieveLogByCommitHash(commitmentHashStr, blockData) {
187
+ const result = await this.getBlock(commitmentHashStr, buffer_1.Buffer.from(blockData.blockhash, "hex"));
188
+ if (result == null)
189
+ return null;
190
+ const [storedBlockHeader, commitHash] = result;
191
+ //Check if block is part of the main chain
192
+ const chainCommitment = await this.contract.get_commit_hash(storedBlockHeader.block_height);
193
+ if (BigInt(chainCommitment) !== BigInt(commitHash))
194
+ return null;
195
+ logger.debug("retrieveLogByCommitHash(): block found," +
196
+ " commit hash: " + commitmentHashStr + " blockhash: " + blockData.blockhash + " height: " + storedBlockHeader.block_height);
197
+ return storedBlockHeader;
198
+ }
199
+ /**
200
+ * Retrieves latest known stored blockheader & blockheader from bitcoin RPC that is in the main chain
201
+ */
202
+ async retrieveLatestKnownBlockLog() {
203
+ const data = await this.Events.findInContractEvents(["btc_relay::events::StoreHeader", "btc_relay::events::StoreForkHeader"], null, async (event) => {
204
+ const storedHeader = StarknetBtcStoredHeader_1.StarknetBtcStoredHeader.fromSerializedFeltArray(event.data);
205
+ const blockHashHex = storedHeader.getBlockHash().toString("hex");
206
+ const commitHash = event.params.commit_hash;
207
+ const [isInBtcMainChain, btcRelayCommitHash] = await Promise.all([
208
+ this.bitcoinRpc.isInMainChain(blockHashHex).catch(() => false),
209
+ this.contract.get_commit_hash(storedHeader.block_height)
210
+ ]);
211
+ if (!isInBtcMainChain)
212
+ return null;
213
+ if (BigInt(commitHash) !== BigInt(btcRelayCommitHash))
214
+ return null;
215
+ return {
216
+ resultStoredHeader: storedHeader,
217
+ resultBitcoinHeader: await this.bitcoinRpc.getBlockHeader(blockHashHex),
218
+ commitHash: commitHash
219
+ };
220
+ });
221
+ if (data != null)
222
+ logger.debug("retrieveLatestKnownBlockLog(): block found," +
223
+ " commit hash: " + (0, Utils_1.toHex)(data.commitHash) + " blockhash: " + data.resultBitcoinHeader.getHash() +
224
+ " height: " + data.resultStoredHeader.getBlockheight());
225
+ return data;
226
+ }
227
+ /**
228
+ * Saves blockheaders as a bitcoin main chain to the btc relay
229
+ *
230
+ * @param signer
231
+ * @param mainHeaders
232
+ * @param storedHeader
233
+ * @param feeRate
234
+ */
235
+ saveMainHeaders(signer, mainHeaders, storedHeader, feeRate) {
236
+ logger.debug("saveMainHeaders(): submitting main blockheaders, count: " + mainHeaders.length);
237
+ return this._saveHeaders(signer, mainHeaders, storedHeader, null, 0, feeRate);
238
+ }
239
+ /**
240
+ * Creates a new long fork and submits the headers to it
241
+ *
242
+ * @param signer
243
+ * @param forkHeaders
244
+ * @param storedHeader
245
+ * @param tipWork
246
+ * @param feeRate
247
+ */
248
+ async saveNewForkHeaders(signer, forkHeaders, storedHeader, tipWork, feeRate) {
249
+ let forkId = Math.floor(Math.random() * 0xFFFFFFFFFFFF);
250
+ logger.debug("saveNewForkHeaders(): submitting new fork & blockheaders," +
251
+ " count: " + forkHeaders.length + " forkId: 0x" + forkId.toString(16));
252
+ return await this._saveHeaders(signer, forkHeaders, storedHeader, tipWork, forkId, feeRate);
253
+ }
254
+ /**
255
+ * Continues submitting blockheaders to a given fork
256
+ *
257
+ * @param signer
258
+ * @param forkHeaders
259
+ * @param storedHeader
260
+ * @param forkId
261
+ * @param tipWork
262
+ * @param feeRate
263
+ */
264
+ saveForkHeaders(signer, forkHeaders, storedHeader, forkId, tipWork, feeRate) {
265
+ logger.debug("saveForkHeaders(): submitting blockheaders to existing fork," +
266
+ " count: " + forkHeaders.length + " forkId: 0x" + forkId.toString(16));
267
+ return this._saveHeaders(signer, forkHeaders, storedHeader, tipWork, forkId, feeRate);
268
+ }
269
+ /**
270
+ * Submits short fork with given blockheaders
271
+ *
272
+ * @param signer
273
+ * @param forkHeaders
274
+ * @param storedHeader
275
+ * @param tipWork
276
+ * @param feeRate
277
+ */
278
+ saveShortForkHeaders(signer, forkHeaders, storedHeader, tipWork, feeRate) {
279
+ logger.debug("saveShortForkHeaders(): submitting short fork blockheaders," +
280
+ " count: " + forkHeaders.length);
281
+ return this._saveHeaders(signer, forkHeaders, storedHeader, tipWork, -1, feeRate);
282
+ }
283
+ /**
284
+ * Estimate required synchronization fee (worst case) to synchronize btc relay to the required blockheight
285
+ *
286
+ * @param requiredBlockheight
287
+ * @param feeRate
288
+ */
289
+ async estimateSynchronizeFee(requiredBlockheight, feeRate) {
290
+ const tipData = await this.getTipData();
291
+ const currBlockheight = tipData.blockheight;
292
+ const blockheightDelta = requiredBlockheight - currBlockheight;
293
+ if (blockheightDelta <= 0)
294
+ return 0n;
295
+ const synchronizationFee = BigInt(blockheightDelta) * await this.getFeePerBlock(feeRate);
296
+ logger.debug("estimateSynchronizeFee(): required blockheight: " + requiredBlockheight +
297
+ " blockheight delta: " + blockheightDelta + " fee: " + synchronizationFee.toString(10));
298
+ return synchronizationFee;
299
+ }
300
+ /**
301
+ * Returns fee required (in SOL) to synchronize a single block to btc relay
302
+ *
303
+ * @param feeRate
304
+ */
305
+ async getFeePerBlock(feeRate) {
306
+ feeRate ?? (feeRate = await this.Chain.Fees.getFeeRate());
307
+ return StarknetFees_1.StarknetFees.getGasFee(GAS_PER_BLOCKHEADER, feeRate);
308
+ }
309
+ /**
310
+ * Gets fee rate required for submitting blockheaders to the main chain
311
+ */
312
+ getMainFeeRate(signer) {
313
+ return this.Chain.Fees.getFeeRate();
314
+ }
315
+ /**
316
+ * Gets fee rate required for submitting blockheaders to the specific fork
317
+ */
318
+ getForkFeeRate(signer, forkId) {
319
+ return this.Chain.Fees.getFeeRate();
320
+ }
321
+ saveInitialHeader(signer, header, epochStart, pastBlocksTimestamps, feeRate) {
322
+ throw new Error("Not supported, starknet contract is initialized with constructor!");
323
+ }
324
+ /**
325
+ * Gets committed header, identified by blockhash & blockheight, determines required BTC relay blockheight based on
326
+ * requiredConfirmations
327
+ * If synchronizer is passed & blockhash is not found, it produces transactions to sync up the btc relay to the
328
+ * current chain tip & adds them to the txs array
329
+ *
330
+ * @param signer
331
+ * @param btcRelay
332
+ * @param btcTxs
333
+ * @param txs solana transaction array, in case we need to synchronize the btc relay ourselves the synchronization
334
+ * txns are added here
335
+ * @param synchronizer optional synchronizer to use to synchronize the btc relay in case it is not yet synchronized
336
+ * to the required blockheight
337
+ * @param feeRate Fee rate to use for synchronization transactions
338
+ * @private
339
+ */
340
+ static async getCommitedHeadersAndSynchronize(signer, btcRelay, btcTxs, txs, synchronizer, feeRate) {
341
+ const leavesTxs = [];
342
+ const blockheaders = {};
343
+ for (let btcTx of btcTxs) {
344
+ const requiredBlockheight = btcTx.blockheight + btcTx.requiredConfirmations - 1;
345
+ const result = await (0, Utils_1.tryWithRetries)(() => btcRelay.retrieveLogAndBlockheight({
346
+ blockhash: btcTx.blockhash
347
+ }, requiredBlockheight));
348
+ if (result != null) {
349
+ blockheaders[result.header.getBlockHash().toString("hex")] = result.header;
350
+ }
351
+ else {
352
+ leavesTxs.push(btcTx);
353
+ }
354
+ }
355
+ if (leavesTxs.length === 0)
356
+ return blockheaders;
357
+ //Need to synchronize
358
+ if (synchronizer == null)
359
+ return null;
360
+ //TODO: We don't have to synchronize to tip, only to our required blockheight
361
+ const resp = await synchronizer.syncToLatestTxs(signer.toString(), feeRate);
362
+ logger.debug("getCommitedHeaderAndSynchronize(): BTC Relay not synchronized to required blockheight, " +
363
+ "synchronizing ourselves in " + resp.txs.length + " txs");
364
+ logger.debug("getCommitedHeaderAndSynchronize(): BTC Relay computed header map: ", resp.computedHeaderMap);
365
+ txs.push(...resp.txs);
366
+ for (let key in resp.computedHeaderMap) {
367
+ const header = resp.computedHeaderMap[key];
368
+ blockheaders[header.getBlockHash().toString("hex")] = header;
369
+ }
370
+ //Check that blockhashes of all the rest txs are included
371
+ for (let btcTx of leavesTxs) {
372
+ if (blockheaders[btcTx.blockhash] == null)
373
+ return null;
374
+ }
375
+ //Retrieve computed headers
376
+ return blockheaders;
377
+ }
378
+ }
379
+ exports.StarknetBtcRelay = StarknetBtcRelay;