@keep-network/tbtc-v2 0.1.1-dev.8 → 0.1.1-dev.82

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 (112) hide show
  1. package/README.adoc +12 -0
  2. package/artifacts/Bank.json +817 -0
  3. package/artifacts/Bridge.json +2644 -0
  4. package/artifacts/Deposit.json +117 -0
  5. package/artifacts/DepositSweep.json +77 -0
  6. package/artifacts/EcdsaDkgValidator.json +532 -0
  7. package/artifacts/EcdsaInactivity.json +156 -0
  8. package/artifacts/EcdsaSortitionPool.json +1004 -0
  9. package/artifacts/Fraud.json +164 -0
  10. package/artifacts/KeepRegistry.json +99 -0
  11. package/artifacts/KeepStake.json +286 -0
  12. package/artifacts/KeepToken.json +711 -0
  13. package/artifacts/KeepTokenStaking.json +483 -0
  14. package/artifacts/MovingFunds.json +249 -0
  15. package/artifacts/NuCypherStakingEscrow.json +256 -0
  16. package/artifacts/NuCypherToken.json +711 -0
  17. package/artifacts/RandomBeaconStub.json +141 -0
  18. package/artifacts/Redemption.json +162 -0
  19. package/artifacts/ReimbursementPool.json +509 -0
  20. package/artifacts/Relay.json +123 -0
  21. package/artifacts/T.json +1148 -0
  22. package/artifacts/TBTC.json +27 -26
  23. package/artifacts/TBTCToken.json +27 -26
  24. package/artifacts/TBTCVault.json +462 -0
  25. package/artifacts/TokenStaking.json +2288 -0
  26. package/artifacts/TokenholderGovernor.json +1795 -0
  27. package/artifacts/TokenholderTimelock.json +1058 -0
  28. package/artifacts/VendingMachine.json +30 -29
  29. package/artifacts/VendingMachineKeep.json +400 -0
  30. package/artifacts/VendingMachineNuCypher.json +400 -0
  31. package/artifacts/WalletRegistry.json +1843 -0
  32. package/artifacts/WalletRegistryGovernance.json +2754 -0
  33. package/artifacts/Wallets.json +186 -0
  34. package/artifacts/solcInputs/5cd0a97e230d515eacf46fb60ea8963a.json +311 -0
  35. package/build/contracts/GovernanceUtils.sol/GovernanceUtils.dbg.json +1 -1
  36. package/build/contracts/GovernanceUtils.sol/GovernanceUtils.json +2 -2
  37. package/build/contracts/bank/Bank.sol/Bank.dbg.json +1 -1
  38. package/build/contracts/bank/Bank.sol/Bank.json +27 -4
  39. package/build/contracts/bank/IReceiveBalanceApproval.sol/IReceiveBalanceApproval.dbg.json +4 -0
  40. package/build/contracts/bank/IReceiveBalanceApproval.sol/IReceiveBalanceApproval.json +34 -0
  41. package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.dbg.json +1 -1
  42. package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.json +2 -2
  43. package/build/contracts/bridge/Bridge.sol/Bridge.dbg.json +1 -1
  44. package/build/contracts/bridge/Bridge.sol/Bridge.json +2516 -196
  45. package/build/contracts/bridge/BridgeState.sol/BridgeState.dbg.json +4 -0
  46. package/build/contracts/bridge/BridgeState.sol/BridgeState.json +226 -0
  47. package/build/contracts/bridge/Deposit.sol/Deposit.dbg.json +4 -0
  48. package/build/contracts/bridge/Deposit.sol/Deposit.json +72 -0
  49. package/build/contracts/bridge/DepositSweep.sol/DepositSweep.dbg.json +4 -0
  50. package/build/contracts/bridge/DepositSweep.sol/DepositSweep.json +30 -0
  51. package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.dbg.json +4 -0
  52. package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.json +10 -0
  53. package/build/contracts/bridge/Fraud.sol/Fraud.dbg.json +4 -0
  54. package/build/contracts/bridge/Fraud.sol/Fraud.json +86 -0
  55. package/build/contracts/bridge/Heartbeat.sol/Heartbeat.dbg.json +4 -0
  56. package/build/contracts/bridge/Heartbeat.sol/Heartbeat.json +10 -0
  57. package/build/contracts/bridge/IRelay.sol/IRelay.dbg.json +4 -0
  58. package/build/contracts/bridge/IRelay.sol/IRelay.json +37 -0
  59. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.dbg.json +4 -0
  60. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.json +138 -0
  61. package/build/contracts/bridge/Redemption.sol/OutboundTx.dbg.json +4 -0
  62. package/build/contracts/bridge/Redemption.sol/OutboundTx.json +10 -0
  63. package/build/contracts/bridge/Redemption.sol/Redemption.dbg.json +4 -0
  64. package/build/contracts/bridge/Redemption.sol/Redemption.json +92 -0
  65. package/build/contracts/bridge/VendingMachine.sol/VendingMachine.dbg.json +1 -1
  66. package/build/contracts/bridge/VendingMachine.sol/VendingMachine.json +2 -2
  67. package/build/contracts/bridge/Wallets.sol/Wallets.dbg.json +4 -0
  68. package/build/contracts/bridge/Wallets.sol/Wallets.json +112 -0
  69. package/build/contracts/token/TBTC.sol/TBTC.dbg.json +1 -1
  70. package/build/contracts/token/TBTC.sol/TBTC.json +2 -2
  71. package/build/contracts/vault/DonationVault.sol/DonationVault.dbg.json +4 -0
  72. package/build/contracts/vault/DonationVault.sol/DonationVault.json +108 -0
  73. package/build/contracts/vault/IVault.sol/IVault.dbg.json +1 -1
  74. package/build/contracts/vault/IVault.sol/IVault.json +24 -1
  75. package/build/contracts/vault/TBTCVault.sol/TBTCVault.dbg.json +1 -1
  76. package/build/contracts/vault/TBTCVault.sol/TBTCVault.json +137 -18
  77. package/contracts/GovernanceUtils.sol +4 -4
  78. package/contracts/bank/Bank.sol +119 -57
  79. package/contracts/bank/IReceiveBalanceApproval.sol +45 -0
  80. package/contracts/bridge/BitcoinTx.sol +232 -10
  81. package/contracts/bridge/Bridge.sol +1601 -244
  82. package/contracts/bridge/BridgeState.sol +739 -0
  83. package/contracts/bridge/Deposit.sol +269 -0
  84. package/contracts/bridge/DepositSweep.sol +571 -0
  85. package/contracts/bridge/EcdsaLib.sol +45 -0
  86. package/contracts/bridge/Fraud.sol +604 -0
  87. package/contracts/bridge/Heartbeat.sol +112 -0
  88. package/contracts/bridge/IRelay.sol +28 -0
  89. package/contracts/bridge/MovingFunds.sol +1089 -0
  90. package/contracts/bridge/Redemption.sol +867 -0
  91. package/contracts/bridge/VendingMachine.sol +1 -1
  92. package/contracts/bridge/Wallets.sol +553 -0
  93. package/contracts/hardhat-dependency-compiler/.hardhat-dependency-compiler +1 -0
  94. package/contracts/hardhat-dependency-compiler/@keep-network/ecdsa/contracts/WalletRegistry.sol +3 -0
  95. package/contracts/hardhat-dependency-compiler/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol +3 -0
  96. package/contracts/hardhat-dependency-compiler/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol +3 -0
  97. package/contracts/token/TBTC.sol +1 -1
  98. package/contracts/vault/DonationVault.sol +125 -0
  99. package/contracts/vault/IVault.sol +19 -13
  100. package/contracts/vault/TBTCVault.sol +69 -19
  101. package/deploy/00_resolve_relay.ts +28 -0
  102. package/deploy/04_deploy_bank.ts +27 -0
  103. package/deploy/05_deploy_bridge.ts +80 -0
  104. package/deploy/06_deploy_tbtc_vault.ts +30 -0
  105. package/deploy/07_bank_update_bridge.ts +19 -0
  106. package/deploy/08_transfer_ownership.ts +15 -0
  107. package/deploy/09_transfer_governance.ts +20 -0
  108. package/deploy/10_transfer_proxy_admin_ownership.ts +30 -0
  109. package/deploy/11_deploy_proxy_admin_with_deputy.ts +33 -0
  110. package/export.json +15993 -475
  111. package/package.json +32 -25
  112. package/artifacts/solcInputs/4cf328e09411ac69d75a3c381680bc2c.json +0 -128
@@ -0,0 +1,45 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ // ██████████████ ▐████▌ ██████████████
4
+ // ██████████████ ▐████▌ ██████████████
5
+ // ▐████▌ ▐████▌
6
+ // ▐████▌ ▐████▌
7
+ // ██████████████ ▐████▌ ██████████████
8
+ // ██████████████ ▐████▌ ██████████████
9
+ // ▐████▌ ▐████▌
10
+ // ▐████▌ ▐████▌
11
+ // ▐████▌ ▐████▌
12
+ // ▐████▌ ▐████▌
13
+ // ▐████▌ ▐████▌
14
+ // ▐████▌ ▐████▌
15
+
16
+ pragma solidity ^0.8.9;
17
+
18
+ /// @title IReceiveBalanceApproval
19
+ /// @notice `IReceiveBalanceApproval` is an interface for a smart contract
20
+ /// consuming Bank balances approved to them in the same transaction by
21
+ /// other contracts or externally owned accounts (EOA).
22
+ interface IReceiveBalanceApproval {
23
+ /// @notice Called by the Bank in `approveBalanceAndCall` function after
24
+ /// the balance `owner` approved `amount` of their balance in the
25
+ /// Bank for the contract. This way, the depositor can approve
26
+ /// balance and call the contract to use the approved balance in
27
+ /// a single transaction.
28
+ /// @param owner Address of the Bank balance owner who approved their
29
+ /// balance to be used by the contract.
30
+ /// @param amount The amount of the Bank balance approved by the owner
31
+ /// to be used by the contract.
32
+ /// @param extraData The `extraData` passed to `Bank.approveBalanceAndCall`.
33
+ // @dev The implementation must ensure this function can only be called
34
+ /// by the Bank. The Bank does _not_ guarantee that the `amount`
35
+ /// approved by the `owner` currently exists on their balance. That is,
36
+ /// the `owner` could approve more balance than they currently have.
37
+ /// This works the same as `Bank.approve` function. The contract must
38
+ /// ensure the actual balance is checked before performing any action
39
+ /// based on it.
40
+ function receiveBalanceApproval(
41
+ address owner,
42
+ uint256 amount,
43
+ bytes memory extraData
44
+ ) external;
45
+ }
@@ -13,20 +13,26 @@
13
13
  // ▐████▌ ▐████▌
14
14
  // ▐████▌ ▐████▌
15
15
 
16
- pragma solidity 0.8.4;
16
+ pragma solidity ^0.8.9;
17
+
18
+ import {BTCUtils} from "@keep-network/bitcoin-spv-sol/contracts/BTCUtils.sol";
19
+ import {BytesLib} from "@keep-network/bitcoin-spv-sol/contracts/BytesLib.sol";
20
+ import {ValidateSPV} from "@keep-network/bitcoin-spv-sol/contracts/ValidateSPV.sol";
21
+
22
+ import "./BridgeState.sol";
17
23
 
18
24
  /// @title Bitcoin transaction
19
25
  /// @notice Allows to reference Bitcoin raw transaction in Solidity.
20
26
  /// @dev See https://developer.bitcoin.org/reference/transactions.html#raw-transaction-format
21
27
  ///
22
- /// Raw Bitcon transaction data:
28
+ /// Raw Bitcoin transaction data:
23
29
  ///
24
30
  /// | Bytes | Name | BTC type | Description |
25
31
  /// |--------|--------------|------------------------|---------------------------|
26
32
  /// | 4 | version | int32_t (LE) | TX version number |
27
33
  /// | varies | tx_in_count | compactSize uint (LE) | Number of TX inputs |
28
34
  /// | varies | tx_in | txIn[] | TX inputs |
29
- /// | varies | tx_out count | compactSize uint (LE) | Number of TX outputs |
35
+ /// | varies | tx_out_count | compactSize uint (LE) | Number of TX outputs |
30
36
  /// | varies | tx_out | txOut[] | TX outputs |
31
37
  /// | 4 | lock_time | uint32_t (LE) | Unix time or block number |
32
38
  ///
@@ -36,8 +42,8 @@ pragma solidity 0.8.4;
36
42
  /// | Bytes | Name | BTC type | Description |
37
43
  /// |--------|------------------|------------------------|---------------------------------------------|
38
44
  /// | 36 | previous_output | outpoint | The previous outpoint being spent |
39
- /// | varies | script bytes | compactSize uint (LE) | The number of bytes in the signature script |
40
- /// | varies | signature script | char[] | The signature script, empty for P2WSH |
45
+ /// | varies | script_bytes | compactSize uint (LE) | The number of bytes in the signature script |
46
+ /// | varies | signature_script | char[] | The signature script, empty for P2WSH |
41
47
  /// | 4 | sequence | uint32_t (LE) | Sequence number |
42
48
  ///
43
49
  ///
@@ -68,17 +74,37 @@ pragma solidity 0.8.4;
68
74
  ///
69
75
  /// (*) compactSize uint is often references as VarInt)
70
76
  ///
77
+ /// Coinbase transaction input (txIn):
78
+ ///
79
+ /// | Bytes | Name | BTC type | Description |
80
+ /// |--------|------------------|------------------------|---------------------------------------------|
81
+ /// | 32 | hash | char[32] | A 32-byte 0x0 null (no previous_outpoint) |
82
+ /// | 4 | index | uint32_t (LE) | 0xffffffff (no previous_outpoint) |
83
+ /// | varies | script_bytes | compactSize uint (LE) | The number of bytes in the coinbase script |
84
+ /// | varies | height | char[] | The block height of this block (BIP34) (*) |
85
+ /// | varies | coinbase_script | none | Arbitrary data, max 100 bytes |
86
+ /// | 4 | sequence | uint32_t (LE) | Sequence number
87
+ ///
88
+ /// (*) Uses script language: starts with a data-pushing opcode that indicates how many bytes to push to
89
+ /// the stack followed by the block height as a little-endian unsigned integer. This script must be as
90
+ /// short as possible, otherwise it may be rejected. The data-pushing opcode will be 0x03 and the total
91
+ /// size four bytes until block 16,777,216 about 300 years from now.
71
92
  library BitcoinTx {
72
- /// @notice Represents Bitcoin transaction data for funding BTC deposit
73
- /// P2(W)SH transaction.
93
+ using BTCUtils for bytes;
94
+ using BTCUtils for uint256;
95
+ using BytesLib for bytes;
96
+ using ValidateSPV for bytes;
97
+ using ValidateSPV for bytes32;
98
+
99
+ /// @notice Represents Bitcoin transaction data.
74
100
  struct Info {
75
- /// @notice Bitcoin transaction version
76
- /// @dev `version` from raw Bitcon transaction data.
101
+ /// @notice Bitcoin transaction version.
102
+ /// @dev `version` from raw Bitcoin transaction data.
77
103
  /// Encoded as 4-bytes signed integer, little endian.
78
104
  bytes4 version;
79
105
  /// @notice All Bitcoin transaction inputs, prepended by the number of
80
106
  /// transaction inputs.
81
- /// @dev `tx_in_count | tx_in` from raw Bitcon transaction data.
107
+ /// @dev `tx_in_count | tx_in` from raw Bitcoin transaction data.
82
108
  ///
83
109
  /// The number of transaction inputs encoded as compactSize
84
110
  /// unsigned integer, little-endian.
@@ -100,5 +126,201 @@ library BitcoinTx {
100
126
  /// @dev `lock_time` from raw Bitcoin transaction data.
101
127
  /// Encoded as 4-bytes unsigned integer, little endian.
102
128
  bytes4 locktime;
129
+ // This struct doesn't contain `__gap` property as the structure is not
130
+ // stored, it is used as a function's calldata argument.
131
+ }
132
+
133
+ /// @notice Represents data needed to perform a Bitcoin SPV proof.
134
+ struct Proof {
135
+ /// @notice The merkle proof of transaction inclusion in a block.
136
+ bytes merkleProof;
137
+ /// @notice Transaction index in the block (0-indexed).
138
+ uint256 txIndexInBlock;
139
+ /// @notice Single byte-string of 80-byte bitcoin headers,
140
+ /// lowest height first.
141
+ bytes bitcoinHeaders;
142
+ // This struct doesn't contain `__gap` property as the structure is not
143
+ // stored, it is used as a function's calldata argument.
144
+ }
145
+
146
+ /// @notice Represents info about an unspent transaction output.
147
+ struct UTXO {
148
+ /// @notice Hash of the transaction the output belongs to.
149
+ /// @dev Byte order corresponds to the Bitcoin internal byte order.
150
+ bytes32 txHash;
151
+ /// @notice Index of the transaction output (0-indexed).
152
+ uint32 txOutputIndex;
153
+ /// @notice Value of the transaction output.
154
+ uint64 txOutputValue;
155
+ // This struct doesn't contain `__gap` property as the structure is not
156
+ // stored, it is used as a function's calldata argument.
157
+ }
158
+
159
+ /// @notice Represents Bitcoin signature in the R/S/V format.
160
+ struct RSVSignature {
161
+ /// @notice Signature r value.
162
+ bytes32 r;
163
+ /// @notice Signature s value.
164
+ bytes32 s;
165
+ /// @notice Signature recovery value.
166
+ uint8 v;
167
+ // This struct doesn't contain `__gap` property as the structure is not
168
+ // stored, it is used as a function's calldata argument.
169
+ }
170
+
171
+ /// @notice Validates the SPV proof of the Bitcoin transaction.
172
+ /// Reverts in case the validation or proof verification fail.
173
+ /// @param txInfo Bitcoin transaction data.
174
+ /// @param proof Bitcoin proof data.
175
+ /// @return txHash Proven 32-byte transaction hash.
176
+ function validateProof(
177
+ BridgeState.Storage storage self,
178
+ Info calldata txInfo,
179
+ Proof calldata proof
180
+ ) internal view returns (bytes32 txHash) {
181
+ require(
182
+ txInfo.inputVector.validateVin(),
183
+ "Invalid input vector provided"
184
+ );
185
+ require(
186
+ txInfo.outputVector.validateVout(),
187
+ "Invalid output vector provided"
188
+ );
189
+
190
+ txHash = abi
191
+ .encodePacked(
192
+ txInfo.version,
193
+ txInfo.inputVector,
194
+ txInfo.outputVector,
195
+ txInfo.locktime
196
+ )
197
+ .hash256View();
198
+
199
+ require(
200
+ txHash.prove(
201
+ proof.bitcoinHeaders.extractMerkleRootLE(),
202
+ proof.merkleProof,
203
+ proof.txIndexInBlock
204
+ ),
205
+ "Tx merkle proof is not valid for provided header and tx hash"
206
+ );
207
+
208
+ evaluateProofDifficulty(self, proof.bitcoinHeaders);
209
+
210
+ return txHash;
211
+ }
212
+
213
+ /// @notice Evaluates the given Bitcoin proof difficulty against the actual
214
+ /// Bitcoin chain difficulty provided by the relay oracle.
215
+ /// Reverts in case the evaluation fails.
216
+ /// @param bitcoinHeaders Bitcoin headers chain being part of the SPV
217
+ /// proof. Used to extract the observed proof difficulty.
218
+ function evaluateProofDifficulty(
219
+ BridgeState.Storage storage self,
220
+ bytes memory bitcoinHeaders
221
+ ) internal view {
222
+ IRelay relay = self.relay;
223
+ uint256 currentEpochDifficulty = relay.getCurrentEpochDifficulty();
224
+ uint256 previousEpochDifficulty = relay.getPrevEpochDifficulty();
225
+
226
+ uint256 requestedDiff = 0;
227
+ uint256 firstHeaderDiff = bitcoinHeaders
228
+ .extractTarget()
229
+ .calculateDifficulty();
230
+
231
+ if (firstHeaderDiff == currentEpochDifficulty) {
232
+ requestedDiff = currentEpochDifficulty;
233
+ } else if (firstHeaderDiff == previousEpochDifficulty) {
234
+ requestedDiff = previousEpochDifficulty;
235
+ } else {
236
+ revert("Not at current or previous difficulty");
237
+ }
238
+
239
+ uint256 observedDiff = bitcoinHeaders.validateHeaderChain();
240
+
241
+ require(
242
+ observedDiff != ValidateSPV.getErrBadLength(),
243
+ "Invalid length of the headers chain"
244
+ );
245
+ require(
246
+ observedDiff != ValidateSPV.getErrInvalidChain(),
247
+ "Invalid headers chain"
248
+ );
249
+ require(
250
+ observedDiff != ValidateSPV.getErrLowWork(),
251
+ "Insufficient work in a header"
252
+ );
253
+
254
+ require(
255
+ observedDiff >= requestedDiff * self.txProofDifficultyFactor,
256
+ "Insufficient accumulated difficulty in header chain"
257
+ );
258
+ }
259
+
260
+ /// @notice Extracts public key hash from the provided P2PKH or P2WPKH output.
261
+ /// Reverts if the validation fails.
262
+ /// @param output The transaction output.
263
+ /// @return pubKeyHash 20-byte public key hash the output locks funds on.
264
+ /// @dev Requirements:
265
+ /// - The output must be of P2PKH or P2WPKH type and lock the funds
266
+ /// on a 20-byte public key hash.
267
+ function extractPubKeyHash(BridgeState.Storage storage, bytes memory output)
268
+ internal
269
+ view
270
+ returns (bytes20 pubKeyHash)
271
+ {
272
+ bytes memory pubKeyHashBytes = output.extractHash();
273
+
274
+ require(
275
+ pubKeyHashBytes.length == 20,
276
+ "Output's public key hash must have 20 bytes"
277
+ );
278
+
279
+ pubKeyHash = pubKeyHashBytes.slice20(0);
280
+
281
+ // We need to make sure that the 20-byte public key hash
282
+ // is actually used in the right context of a P2PKH or P2WPKH
283
+ // output. To do so, we must extract the full script from the output
284
+ // and compare with the expected P2PKH and P2WPKH scripts
285
+ // referring to that 20-byte public key hash. The output consists
286
+ // of an 8-byte value and a variable length script. To extract the
287
+ // script we slice the output starting from 9th byte until the end.
288
+ bytes32 outputScriptKeccak = keccak256(
289
+ output.slice(8, output.length - 8)
290
+ );
291
+ // Build the expected P2PKH script which has the following byte
292
+ // format: <0x1976a914> <20-byte PKH> <0x88ac>. According to
293
+ // https://en.bitcoin.it/wiki/Script#Opcodes this translates to:
294
+ // - 0x19: Byte length of the entire script
295
+ // - 0x76: OP_DUP
296
+ // - 0xa9: OP_HASH160
297
+ // - 0x14: Byte length of the public key hash
298
+ // - 0x88: OP_EQUALVERIFY
299
+ // - 0xac: OP_CHECKSIG
300
+ // which matches the P2PKH structure as per:
301
+ // https://en.bitcoin.it/wiki/Transaction#Pay-to-PubkeyHash
302
+ bytes32 P2PKHScriptKeccak = keccak256(
303
+ abi.encodePacked(hex"1976a914", pubKeyHash, hex"88ac")
304
+ );
305
+ // Build the expected P2WPKH script which has the following format:
306
+ // <0x160014> <20-byte PKH>. According to
307
+ // https://en.bitcoin.it/wiki/Script#Opcodes this translates to:
308
+ // - 0x16: Byte length of the entire script
309
+ // - 0x00: OP_0
310
+ // - 0x14: Byte length of the public key hash
311
+ // which matches the P2WPKH structure as per:
312
+ // https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#P2WPKH
313
+ bytes32 P2WPKHScriptKeccak = keccak256(
314
+ abi.encodePacked(hex"160014", pubKeyHash)
315
+ );
316
+ // Make sure the actual output script matches either the P2PKH
317
+ // or P2WPKH format.
318
+ require(
319
+ outputScriptKeccak == P2PKHScriptKeccak ||
320
+ outputScriptKeccak == P2WPKHScriptKeccak,
321
+ "Output must be P2PKH or P2WPKH"
322
+ );
323
+
324
+ return pubKeyHash;
103
325
  }
104
326
  }