@keep-network/tbtc-v2 0.1.1-dev.6 → 0.1.1-dev.60

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 (95) hide show
  1. package/README.adoc +12 -0
  2. package/artifacts/Bank.json +752 -0
  3. package/artifacts/Bridge.json +3962 -0
  4. package/artifacts/Deposit.json +117 -0
  5. package/artifacts/DepositSweep.json +76 -0
  6. package/artifacts/EcdsaDkgValidator.json +532 -0
  7. package/artifacts/EcdsaInactivity.json +156 -0
  8. package/artifacts/Fraud.json +154 -0
  9. package/artifacts/KeepRegistry.json +99 -0
  10. package/artifacts/KeepStake.json +286 -0
  11. package/artifacts/KeepToken.json +711 -0
  12. package/artifacts/KeepTokenStaking.json +483 -0
  13. package/artifacts/MovingFunds.json +227 -0
  14. package/artifacts/NuCypherStakingEscrow.json +256 -0
  15. package/artifacts/NuCypherToken.json +711 -0
  16. package/artifacts/RandomBeaconStub.json +141 -0
  17. package/artifacts/Redemption.json +162 -0
  18. package/artifacts/ReimbursementPool.json +509 -0
  19. package/artifacts/Relay.json +123 -0
  20. package/artifacts/SortitionPool.json +944 -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/TokenStaking.json +2288 -0
  25. package/artifacts/TokenholderGovernor.json +1795 -0
  26. package/artifacts/TokenholderTimelock.json +1058 -0
  27. package/artifacts/VendingMachine.json +30 -29
  28. package/artifacts/VendingMachineKeep.json +400 -0
  29. package/artifacts/VendingMachineNuCypher.json +400 -0
  30. package/artifacts/WalletRegistry.json +2709 -0
  31. package/artifacts/WalletRegistryGovernance.json +2364 -0
  32. package/artifacts/Wallets.json +186 -0
  33. package/artifacts/solcInputs/59994c0eff9c9c3b454733a65b82146c.json +218 -0
  34. package/build/contracts/GovernanceUtils.sol/GovernanceUtils.dbg.json +1 -1
  35. package/build/contracts/GovernanceUtils.sol/GovernanceUtils.json +2 -2
  36. package/build/contracts/bank/Bank.sol/Bank.dbg.json +1 -1
  37. package/build/contracts/bank/Bank.sol/Bank.json +20 -2
  38. package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.dbg.json +4 -0
  39. package/build/contracts/bridge/BitcoinTx.sol/BitcoinTx.json +10 -0
  40. package/build/contracts/bridge/Bridge.sol/Bridge.dbg.json +1 -1
  41. package/build/contracts/bridge/Bridge.sol/Bridge.json +2470 -132
  42. package/build/contracts/bridge/BridgeState.sol/BridgeState.dbg.json +4 -0
  43. package/build/contracts/bridge/BridgeState.sol/BridgeState.json +220 -0
  44. package/build/contracts/bridge/Deposit.sol/Deposit.dbg.json +4 -0
  45. package/build/contracts/bridge/Deposit.sol/Deposit.json +72 -0
  46. package/build/contracts/bridge/DepositSweep.sol/DepositSweep.dbg.json +4 -0
  47. package/build/contracts/bridge/DepositSweep.sol/DepositSweep.json +30 -0
  48. package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.dbg.json +4 -0
  49. package/build/contracts/bridge/EcdsaLib.sol/EcdsaLib.json +10 -0
  50. package/build/contracts/bridge/Fraud.sol/Fraud.dbg.json +4 -0
  51. package/build/contracts/bridge/Fraud.sol/Fraud.json +86 -0
  52. package/build/contracts/bridge/IRelay.sol/IRelay.dbg.json +4 -0
  53. package/build/contracts/bridge/IRelay.sol/IRelay.json +37 -0
  54. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.dbg.json +4 -0
  55. package/build/contracts/bridge/MovingFunds.sol/MovingFunds.json +125 -0
  56. package/build/contracts/bridge/Redemption.sol/OutboundTx.dbg.json +4 -0
  57. package/build/contracts/bridge/Redemption.sol/OutboundTx.json +10 -0
  58. package/build/contracts/bridge/Redemption.sol/Redemption.dbg.json +4 -0
  59. package/build/contracts/bridge/Redemption.sol/Redemption.json +92 -0
  60. package/build/contracts/bridge/VendingMachine.sol/VendingMachine.dbg.json +1 -1
  61. package/build/contracts/bridge/VendingMachine.sol/VendingMachine.json +2 -2
  62. package/build/contracts/bridge/Wallets.sol/Wallets.dbg.json +4 -0
  63. package/build/contracts/bridge/Wallets.sol/Wallets.json +112 -0
  64. package/build/contracts/token/TBTC.sol/TBTC.dbg.json +1 -1
  65. package/build/contracts/token/TBTC.sol/TBTC.json +2 -2
  66. package/build/contracts/vault/IVault.sol/IVault.dbg.json +1 -1
  67. package/build/contracts/vault/IVault.sol/IVault.json +19 -1
  68. package/build/contracts/vault/TBTCVault.sol/TBTCVault.dbg.json +1 -1
  69. package/build/contracts/vault/TBTCVault.sol/TBTCVault.json +36 -18
  70. package/contracts/GovernanceUtils.sol +1 -1
  71. package/contracts/bank/Bank.sol +34 -18
  72. package/contracts/bridge/BitcoinTx.sol +303 -0
  73. package/contracts/bridge/Bridge.sol +1527 -247
  74. package/contracts/bridge/BridgeState.sol +698 -0
  75. package/contracts/bridge/Deposit.sol +266 -0
  76. package/contracts/bridge/DepositSweep.sol +514 -0
  77. package/contracts/bridge/EcdsaLib.sol +45 -0
  78. package/contracts/bridge/Fraud.sol +508 -0
  79. package/contracts/bridge/IRelay.sol +28 -0
  80. package/contracts/bridge/MovingFunds.sol +1034 -0
  81. package/contracts/bridge/Redemption.sol +868 -0
  82. package/contracts/bridge/VendingMachine.sol +1 -1
  83. package/contracts/bridge/Wallets.sol +550 -0
  84. package/contracts/token/TBTC.sol +1 -1
  85. package/contracts/vault/IVault.sol +32 -10
  86. package/contracts/vault/TBTCVault.sol +20 -2
  87. package/deploy/00_resolve_relay.ts +28 -0
  88. package/deploy/04_deploy_bank.ts +27 -0
  89. package/deploy/05_deploy_bridge.ts +67 -0
  90. package/deploy/06_bank_update_bridge.ts +19 -0
  91. package/deploy/07_transfer_ownership.ts +15 -0
  92. package/deploy/08_transfer_governance.ts +20 -0
  93. package/export.json +15711 -475
  94. package/package.json +27 -24
  95. package/artifacts/solcInputs/c4fd2c31cc58f5fe0cc586dd84a84b60.json +0 -125
@@ -0,0 +1,303 @@
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
+ 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";
23
+
24
+ /// @title Bitcoin transaction
25
+ /// @notice Allows to reference Bitcoin raw transaction in Solidity.
26
+ /// @dev See https://developer.bitcoin.org/reference/transactions.html#raw-transaction-format
27
+ ///
28
+ /// Raw Bitcoin transaction data:
29
+ ///
30
+ /// | Bytes | Name | BTC type | Description |
31
+ /// |--------|--------------|------------------------|---------------------------|
32
+ /// | 4 | version | int32_t (LE) | TX version number |
33
+ /// | varies | tx_in_count | compactSize uint (LE) | Number of TX inputs |
34
+ /// | varies | tx_in | txIn[] | TX inputs |
35
+ /// | varies | tx_out count | compactSize uint (LE) | Number of TX outputs |
36
+ /// | varies | tx_out | txOut[] | TX outputs |
37
+ /// | 4 | lock_time | uint32_t (LE) | Unix time or block number |
38
+ ///
39
+ //
40
+ /// Non-coinbase transaction input (txIn):
41
+ ///
42
+ /// | Bytes | Name | BTC type | Description |
43
+ /// |--------|------------------|------------------------|---------------------------------------------|
44
+ /// | 36 | previous_output | outpoint | The previous outpoint being spent |
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 |
47
+ /// | 4 | sequence | uint32_t (LE) | Sequence number |
48
+ ///
49
+ ///
50
+ /// The reference to transaction being spent (outpoint):
51
+ ///
52
+ /// | Bytes | Name | BTC type | Description |
53
+ /// |-------|-------|---------------|------------------------------------------|
54
+ /// | 32 | hash | char[32] | Hash of the transaction to spend |
55
+ /// | 4 | index | uint32_t (LE) | Index of the specific output from the TX |
56
+ ///
57
+ ///
58
+ /// Transaction output (txOut):
59
+ ///
60
+ /// | Bytes | Name | BTC type | Description |
61
+ /// |--------|-----------------|-----------------------|--------------------------------------|
62
+ /// | 8 | value | int64_t (LE) | Number of satoshis to spend |
63
+ /// | 1+ | pk_script_bytes | compactSize uint (LE) | Number of bytes in the pubkey script |
64
+ /// | varies | pk_script | char[] | Pubkey script |
65
+ ///
66
+ /// compactSize uint format:
67
+ ///
68
+ /// | Value | Bytes | Format |
69
+ /// |-----------------------------------------|-------|----------------------------------------------|
70
+ /// | >= 0 && <= 252 | 1 | uint8_t |
71
+ /// | >= 253 && <= 0xffff | 3 | 0xfd followed by the number as uint16_t (LE) |
72
+ /// | >= 0x10000 && <= 0xffffffff | 5 | 0xfe followed by the number as uint32_t (LE) |
73
+ /// | >= 0x100000000 && <= 0xffffffffffffffff | 9 | 0xff followed by the number as uint64_t (LE) |
74
+ ///
75
+ /// (*) compactSize uint is often references as VarInt)
76
+ ///
77
+ library BitcoinTx {
78
+ using BTCUtils for bytes;
79
+ using BTCUtils for uint256;
80
+ using BytesLib for bytes;
81
+ using ValidateSPV for bytes;
82
+ using ValidateSPV for bytes32;
83
+
84
+ /// @notice Represents Bitcoin transaction data.
85
+ struct Info {
86
+ /// @notice Bitcoin transaction version
87
+ /// @dev `version` from raw Bitcoin transaction data.
88
+ /// Encoded as 4-bytes signed integer, little endian.
89
+ bytes4 version;
90
+ /// @notice All Bitcoin transaction inputs, prepended by the number of
91
+ /// transaction inputs.
92
+ /// @dev `tx_in_count | tx_in` from raw Bitcoin transaction data.
93
+ ///
94
+ /// The number of transaction inputs encoded as compactSize
95
+ /// unsigned integer, little-endian.
96
+ ///
97
+ /// Note that some popular block explorers reverse the order of
98
+ /// bytes from `outpoint`'s `hash` and display it as big-endian.
99
+ /// Solidity code of Bridge expects hashes in little-endian, just
100
+ /// like they are represented in a raw Bitcoin transaction.
101
+ bytes inputVector;
102
+ /// @notice All Bitcoin transaction outputs prepended by the number of
103
+ /// transaction outputs.
104
+ /// @dev `tx_out_count | tx_out` from raw Bitcoin transaction data.
105
+ ///
106
+ /// The number of transaction outputs encoded as a compactSize
107
+ /// unsigned integer, little-endian.
108
+ bytes outputVector;
109
+ /// @notice Bitcoin transaction locktime.
110
+ ///
111
+ /// @dev `lock_time` from raw Bitcoin transaction data.
112
+ /// Encoded as 4-bytes unsigned integer, little endian.
113
+ bytes4 locktime;
114
+ }
115
+
116
+ /// @notice Represents data needed to perform a Bitcoin SPV proof.
117
+ struct Proof {
118
+ /// @notice The merkle proof of transaction inclusion in a block.
119
+ bytes merkleProof;
120
+ /// @notice Transaction index in the block (0-indexed).
121
+ uint256 txIndexInBlock;
122
+ /// @notice Single byte-string of 80-byte bitcoin headers,
123
+ /// lowest height first.
124
+ bytes bitcoinHeaders;
125
+ }
126
+
127
+ /// @notice Represents info about an unspent transaction output.
128
+ struct UTXO {
129
+ /// @notice Hash of the transaction the output belongs to.
130
+ /// @dev Byte order corresponds to the Bitcoin internal byte order.
131
+ bytes32 txHash;
132
+ /// @notice Index of the transaction output (0-indexed).
133
+ uint32 txOutputIndex;
134
+ /// @notice Value of the transaction output.
135
+ uint64 txOutputValue;
136
+ }
137
+
138
+ /// @notice Represents Bitcoin signature in the R/S/V format.
139
+ struct RSVSignature {
140
+ /// @notice Signature r value.
141
+ bytes32 r;
142
+ /// @notice Signature s value.
143
+ bytes32 s;
144
+ /// @notice Signature recovery value.
145
+ uint8 v;
146
+ }
147
+
148
+ /// @notice Validates the SPV proof of the Bitcoin transaction.
149
+ /// Reverts in case the validation or proof verification fail.
150
+ /// @param txInfo Bitcoin transaction data
151
+ /// @param proof Bitcoin proof data
152
+ /// @return txHash Proven 32-byte transaction hash.
153
+ function validateProof(
154
+ BridgeState.Storage storage self,
155
+ Info calldata txInfo,
156
+ Proof calldata proof
157
+ ) internal view returns (bytes32 txHash) {
158
+ require(
159
+ txInfo.inputVector.validateVin(),
160
+ "Invalid input vector provided"
161
+ );
162
+ require(
163
+ txInfo.outputVector.validateVout(),
164
+ "Invalid output vector provided"
165
+ );
166
+
167
+ txHash = abi
168
+ .encodePacked(
169
+ txInfo.version,
170
+ txInfo.inputVector,
171
+ txInfo.outputVector,
172
+ txInfo.locktime
173
+ )
174
+ .hash256View();
175
+
176
+ require(
177
+ txHash.prove(
178
+ proof.bitcoinHeaders.extractMerkleRootLE(),
179
+ proof.merkleProof,
180
+ proof.txIndexInBlock
181
+ ),
182
+ "Tx merkle proof is not valid for provided header and tx hash"
183
+ );
184
+
185
+ evaluateProofDifficulty(self, proof.bitcoinHeaders);
186
+
187
+ return txHash;
188
+ }
189
+
190
+ /// @notice Evaluates the given Bitcoin proof difficulty against the actual
191
+ /// Bitcoin chain difficulty provided by the relay oracle.
192
+ /// Reverts in case the evaluation fails.
193
+ /// @param bitcoinHeaders Bitcoin headers chain being part of the SPV
194
+ /// proof. Used to extract the observed proof difficulty
195
+ function evaluateProofDifficulty(
196
+ BridgeState.Storage storage self,
197
+ bytes memory bitcoinHeaders
198
+ ) internal view {
199
+ IRelay relay = self.relay;
200
+ uint256 currentEpochDifficulty = relay.getCurrentEpochDifficulty();
201
+ uint256 previousEpochDifficulty = relay.getPrevEpochDifficulty();
202
+
203
+ uint256 requestedDiff = 0;
204
+ uint256 firstHeaderDiff = bitcoinHeaders
205
+ .extractTarget()
206
+ .calculateDifficulty();
207
+
208
+ if (firstHeaderDiff == currentEpochDifficulty) {
209
+ requestedDiff = currentEpochDifficulty;
210
+ } else if (firstHeaderDiff == previousEpochDifficulty) {
211
+ requestedDiff = previousEpochDifficulty;
212
+ } else {
213
+ revert("Not at current or previous difficulty");
214
+ }
215
+
216
+ uint256 observedDiff = bitcoinHeaders.validateHeaderChain();
217
+
218
+ require(
219
+ observedDiff != ValidateSPV.getErrBadLength(),
220
+ "Invalid length of the headers chain"
221
+ );
222
+ require(
223
+ observedDiff != ValidateSPV.getErrInvalidChain(),
224
+ "Invalid headers chain"
225
+ );
226
+ require(
227
+ observedDiff != ValidateSPV.getErrLowWork(),
228
+ "Insufficient work in a header"
229
+ );
230
+
231
+ require(
232
+ observedDiff >= requestedDiff * self.txProofDifficultyFactor,
233
+ "Insufficient accumulated difficulty in header chain"
234
+ );
235
+ }
236
+
237
+ /// @notice Extracts public key hash from the provided P2PKH or P2WPKH output.
238
+ /// Reverts if the validation fails.
239
+ /// @param output The transaction output
240
+ /// @return pubKeyHash 20-byte public key hash the output locks funds on
241
+ /// @dev Requirements:
242
+ /// - The output must be of P2PKH or P2WPKH type and lock the funds
243
+ /// on a 20-byte public key hash
244
+ function extractPubKeyHash(BridgeState.Storage storage, bytes memory output)
245
+ internal
246
+ view
247
+ returns (bytes20 pubKeyHash)
248
+ {
249
+ bytes memory pubKeyHashBytes = output.extractHash();
250
+
251
+ require(
252
+ pubKeyHashBytes.length == 20,
253
+ "Output's public key hash must have 20 bytes"
254
+ );
255
+
256
+ pubKeyHash = pubKeyHashBytes.slice20(0);
257
+
258
+ // We need to make sure that the 20-byte public key hash
259
+ // is actually used in the right context of a P2PKH or P2WPKH
260
+ // output. To do so, we must extract the full script from the output
261
+ // and compare with the expected P2PKH and P2WPKH scripts
262
+ // referring to that 20-byte public key hash. The output consists
263
+ // of an 8-byte value and a variable length script. To extract the
264
+ // script we slice the output starting from 9th byte until the end.
265
+ bytes32 outputScriptKeccak = keccak256(
266
+ output.slice(8, output.length - 8)
267
+ );
268
+ // Build the expected P2PKH script which has the following byte
269
+ // format: <0x1976a914> <20-byte PKH> <0x88ac>. According to
270
+ // https://en.bitcoin.it/wiki/Script#Opcodes this translates to:
271
+ // - 0x19: Byte length of the entire script
272
+ // - 0x76: OP_DUP
273
+ // - 0xa9: OP_HASH160
274
+ // - 0x14: Byte length of the public key hash
275
+ // - 0x88: OP_EQUALVERIFY
276
+ // - 0xac: OP_CHECKSIG
277
+ // which matches the P2PKH structure as per:
278
+ // https://en.bitcoin.it/wiki/Transaction#Pay-to-PubkeyHash
279
+ bytes32 P2PKHScriptKeccak = keccak256(
280
+ abi.encodePacked(hex"1976a914", pubKeyHash, hex"88ac")
281
+ );
282
+ // Build the expected P2WPKH script which has the following format:
283
+ // <0x160014> <20-byte PKH>. According to
284
+ // https://en.bitcoin.it/wiki/Script#Opcodes this translates to:
285
+ // - 0x16: Byte length of the entire script
286
+ // - 0x00: OP_0
287
+ // - 0x14: Byte length of the public key hash
288
+ // which matches the P2WPKH structure as per:
289
+ // https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#P2WPKH
290
+ bytes32 P2WPKHScriptKeccak = keccak256(
291
+ abi.encodePacked(hex"160014", pubKeyHash)
292
+ );
293
+ // Make sure the actual output script matches either the P2PKH
294
+ // or P2WPKH format.
295
+ require(
296
+ outputScriptKeccak == P2PKHScriptKeccak ||
297
+ outputScriptKeccak == P2WPKHScriptKeccak,
298
+ "Output must be P2PKH or P2WPKH"
299
+ );
300
+
301
+ return pubKeyHash;
302
+ }
303
+ }