@rsksmart/btc-transaction-solidity-helper 0.0.3 → 0.2.1
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/Readme.md +5 -3
- package/contracts/BtcUtils.sol +209 -31
- package/contracts/OpCodes.sol +15 -0
- package/package.json +5 -3
package/Readme.md
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
# Bitcoin Transaction Solidity Helper
|
|
2
|
+
[](https://scorecard.dev/viewer/?uri=github.com/rsksmart/btc-transaction-solidity-helper)
|
|
2
3
|
|
|
3
4
|
The intention of this library is to make easier to work with Bitcoin transactions in Solidity smart contracts. Since Rootstock extends Bitcoin's capabilities by enabling smart contracts it is important to be able to work with Bitcoin transactions in them.
|
|
4
5
|
|
|
5
6
|
## Features
|
|
6
7
|
|
|
7
8
|
The features of this library include:
|
|
8
|
-
* Bitcoin transaction output parsing: is able to receive a raw tx and return an array of
|
|
9
|
+
* Bitcoin transaction output parsing: is able to receive a raw tx and return an array of structures with the tx outputs
|
|
9
10
|
* Bitcoin transaction hashing: is able to receive a raw tx and return its hash
|
|
10
|
-
* Bitcoin transaction output script validation: is able to receive a raw output script, validate that is from a specific type and return a result. E.g. receive a raw null-data script and return the
|
|
11
|
+
* Bitcoin transaction output script validation: is able to receive a raw output script, validate that is from a specific type and return a result. E.g. receive a raw null-data script and return the embedded data in it
|
|
11
12
|
* Bitcoin address generation: is able to generate Bitcoin the address from a specific script and also to validate if a given address was generated from a script or not.
|
|
13
|
+
* Bitcoin address validation: is able to validate if a Bitcoin address is of a given type or not.
|
|
12
14
|
|
|
13
15
|
### Future features
|
|
14
16
|
These are some features that can increase the library capabilities in the future:
|
|
@@ -28,4 +30,4 @@ These are some features that can increase the library capabilities in the future
|
|
|
28
30
|
```solidity
|
|
29
31
|
BtcUtils.TxRawOutput[] memory outputs = BtcUtils.getOutputs(btcTx);
|
|
30
32
|
bytes memory btcTxDestination = BtcUtils.parseNullDataScript(outputs[0].pkScript, false);
|
|
31
|
-
```
|
|
33
|
+
```
|
package/contracts/BtcUtils.sol
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
2
|
pragma solidity ^0.8.18;
|
|
3
3
|
|
|
4
|
+
import "./OpCodes.sol";
|
|
5
|
+
|
|
4
6
|
/**
|
|
5
7
|
* @title BtcUtils
|
|
6
8
|
* @notice This library contains functionality to make easier to work with Bitcoin transactions in Solidity.
|
|
@@ -10,11 +12,27 @@ pragma solidity ^0.8.18;
|
|
|
10
12
|
library BtcUtils {
|
|
11
13
|
uint8 private constant MAX_COMPACT_SIZE_LENGTH = 252;
|
|
12
14
|
uint8 private constant MAX_BYTES_USED_FOR_COMPACT_SIZE = 8;
|
|
15
|
+
|
|
16
|
+
uint private constant HASH160_SIZE = 20;
|
|
17
|
+
uint private constant SHA256_SIZE = 32;
|
|
18
|
+
uint private constant TAPROOT_PUBKEY_SIZE = 32;
|
|
19
|
+
|
|
13
20
|
uint8 private constant OUTPOINT_SIZE = 36;
|
|
14
21
|
uint8 private constant OUTPUT_VALUE_SIZE = 8;
|
|
15
|
-
|
|
22
|
+
|
|
16
23
|
uint8 private constant PUBKEY_HASH_START = 3;
|
|
17
|
-
|
|
24
|
+
bytes1 private constant PUBKEY_HASH_MAINNET_BYTE = 0x00;
|
|
25
|
+
bytes1 private constant PUBKEY_HASH_TESTNET_BYTE = 0x6f;
|
|
26
|
+
|
|
27
|
+
uint8 private constant SCRIPT_HASH_START = 2;
|
|
28
|
+
bytes1 private constant SCRIPT_HASH_MAINNET_BYTE = 0x05;
|
|
29
|
+
bytes1 private constant SCRIPT_HASH_TESTNET_BYTE = 0xc4;
|
|
30
|
+
|
|
31
|
+
uint private constant BECH32_WORD_SIZE = 5;
|
|
32
|
+
uint private constant BYTE_SIZE = 8;
|
|
33
|
+
|
|
34
|
+
bytes1 private constant WITNESS_VERSION_0 = 0x00;
|
|
35
|
+
bytes1 private constant WITNESS_VERSION_1 = 0x01;
|
|
18
36
|
|
|
19
37
|
|
|
20
38
|
/**
|
|
@@ -28,6 +46,10 @@ library BtcUtils {
|
|
|
28
46
|
uint256 totalSize;
|
|
29
47
|
}
|
|
30
48
|
|
|
49
|
+
function version() external pure returns (string memory) {
|
|
50
|
+
return "0.2.1";
|
|
51
|
+
}
|
|
52
|
+
|
|
31
53
|
/// @notice Parse a raw transaction to get an array of its outputs in a structured representation
|
|
32
54
|
/// @param rawTx the raw transaction
|
|
33
55
|
/// @return An array of `TxRawOutput` with the outputs of the transaction
|
|
@@ -61,7 +83,7 @@ library BtcUtils {
|
|
|
61
83
|
}
|
|
62
84
|
|
|
63
85
|
function extractRawOutput(uint position, bytes memory rawTx) private pure returns (TxRawOutput memory) {
|
|
64
|
-
TxRawOutput memory result;
|
|
86
|
+
TxRawOutput memory result = TxRawOutput(0, "", 0, 0);
|
|
65
87
|
result.value = uint64(calculateLittleEndianFragment(position, position + OUTPUT_VALUE_SIZE, rawTx));
|
|
66
88
|
position += OUTPUT_VALUE_SIZE;
|
|
67
89
|
|
|
@@ -78,42 +100,164 @@ library BtcUtils {
|
|
|
78
100
|
return result;
|
|
79
101
|
}
|
|
80
102
|
|
|
81
|
-
/// @notice Parse a raw
|
|
103
|
+
/// @notice Parse a raw output script whose type is not known by the consumer. The function will
|
|
104
|
+
/// return the corresponding address if the type of the script is supported or an error if not.
|
|
105
|
+
/// For the addresses that are encoded with base58check the checksum bytes are not included in
|
|
106
|
+
/// the resulting byte array
|
|
107
|
+
/// @param outputScript the fragment of the raw transaction containing the raw output script
|
|
108
|
+
/// @param mainnet if the address to generate is from mainnet or testnet
|
|
109
|
+
/// @return The address bytes regarless of the output script type
|
|
110
|
+
function outputScriptToAddress(bytes calldata outputScript, bool mainnet) public pure returns (bytes memory) {
|
|
111
|
+
if (isP2PKHOutput(outputScript)) {
|
|
112
|
+
return parsePayToPubKeyHash(outputScript, mainnet);
|
|
113
|
+
}
|
|
114
|
+
if (isP2SHOutput(outputScript)) {
|
|
115
|
+
return parsePayToScriptHash(outputScript, mainnet);
|
|
116
|
+
}
|
|
117
|
+
if (isP2WPKHOutput(outputScript)) {
|
|
118
|
+
return parsePayToWitnessPubKeyHash(outputScript);
|
|
119
|
+
}
|
|
120
|
+
if (isP2WSHOutput(outputScript)) {
|
|
121
|
+
return parsePayToWitnessScriptHash(outputScript);
|
|
122
|
+
}
|
|
123
|
+
if (isP2TROutput(outputScript)) {
|
|
124
|
+
return parsePayToTaproot(outputScript);
|
|
125
|
+
}
|
|
126
|
+
revert("Unsupported script type");
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/// @notice Check if a raw output script is a pay-to-public-key-hash output
|
|
130
|
+
/// @param pkScript the fragment of the raw transaction containing the raw output script
|
|
131
|
+
/// @return Whether the script has a pay-to-public-key-hash output structure or not
|
|
132
|
+
function isP2PKHOutput(bytes memory pkScript) public pure returns (bool) {
|
|
133
|
+
return pkScript.length == 5 + HASH160_SIZE &&
|
|
134
|
+
pkScript[0] == OpCodes.OP_DUP &&
|
|
135
|
+
pkScript[1] == OpCodes.OP_HASH160 &&
|
|
136
|
+
uint8(pkScript[2]) == HASH160_SIZE &&
|
|
137
|
+
pkScript[23] == OpCodes.OP_EQUALVERIFY &&
|
|
138
|
+
pkScript[24] == OpCodes.OP_CHECKSIG;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/// @notice Check if a raw output script is a pay-to-script-hash output
|
|
142
|
+
/// @param pkScript the fragment of the raw transaction containing the raw output script
|
|
143
|
+
/// @return Whether the script has a pay-to-script-hash output structure or not
|
|
144
|
+
function isP2SHOutput(bytes memory pkScript) public pure returns (bool) {
|
|
145
|
+
return pkScript.length == 3 + HASH160_SIZE &&
|
|
146
|
+
pkScript[0] == OpCodes.OP_HASH160 &&
|
|
147
|
+
uint8(pkScript[1]) == HASH160_SIZE &&
|
|
148
|
+
pkScript[22] == OpCodes.OP_EQUAL;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/// @notice Check if a raw output script is a pay-to-witness-pubkey-hash output
|
|
152
|
+
/// @param pkScript the fragment of the raw transaction containing the raw output script
|
|
153
|
+
/// @return Whether the script has a pay-to-witness-pubkey-hash output structure or not
|
|
154
|
+
function isP2WPKHOutput(bytes memory pkScript) public pure returns (bool) {
|
|
155
|
+
return pkScript.length == 2 + HASH160_SIZE &&
|
|
156
|
+
pkScript[0] == OpCodes.OP_0 &&
|
|
157
|
+
uint8(pkScript[1]) == HASH160_SIZE;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/// @notice Check if a raw output script is a pay-to-witness-script-hash output
|
|
161
|
+
/// @param pkScript the fragment of the raw transaction containing the raw output script
|
|
162
|
+
/// @return Whether the script has a pay-to-witness-script-hash output structure or not
|
|
163
|
+
function isP2WSHOutput(bytes memory pkScript) public pure returns (bool) {
|
|
164
|
+
return pkScript.length == 2 + SHA256_SIZE &&
|
|
165
|
+
pkScript[0] == OpCodes.OP_0 &&
|
|
166
|
+
uint8(pkScript[1]) == SHA256_SIZE;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/// @notice Check if a raw output script is a pay-to-taproot output
|
|
170
|
+
/// @notice Reference for implementation: https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki
|
|
171
|
+
/// @param pkScript the fragment of the raw transaction containing the raw output script
|
|
172
|
+
/// @return Whether the script has a pay-to-taproot output structure or not
|
|
173
|
+
function isP2TROutput(bytes memory pkScript) public pure returns (bool) {
|
|
174
|
+
return pkScript.length == 2 + TAPROOT_PUBKEY_SIZE &&
|
|
175
|
+
pkScript[0] == OpCodes.OP_1 &&
|
|
176
|
+
uint8(pkScript[1]) == TAPROOT_PUBKEY_SIZE;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/// @notice Parse a raw pay-to-public-key-hash output script to get the corresponding address,
|
|
180
|
+
/// the resulting byte array doesn't include the checksum bytes of the base58check encoding at
|
|
181
|
+
/// the end
|
|
82
182
|
/// @param outputScript the fragment of the raw transaction containing the raw output script
|
|
83
183
|
/// @param mainnet if the address to generate is from mainnet or testnet
|
|
84
184
|
/// @return The address generated using the receiver's public key hash
|
|
85
185
|
function parsePayToPubKeyHash(bytes calldata outputScript, bool mainnet) public pure returns (bytes memory) {
|
|
86
|
-
require(outputScript
|
|
87
|
-
require(
|
|
88
|
-
outputScript[0] == 0x76 && // OP_DUP
|
|
89
|
-
outputScript[1] == 0xa9 && // OP_HASH160
|
|
90
|
-
outputScript[2] == 0x14 && // pubKeyHashSize, should be always 14 (20B)
|
|
91
|
-
outputScript[23] == 0x88 && // OP_EQUALVERIFY
|
|
92
|
-
outputScript[24] == 0xac, // OP_CHECKSIG
|
|
93
|
-
"Script has not the required structure"
|
|
94
|
-
);
|
|
186
|
+
require(isP2PKHOutput(outputScript), "Script hasn't the required structure");
|
|
95
187
|
|
|
96
|
-
bytes memory destinationAddress = new bytes(
|
|
97
|
-
for(uint8 i = PUBKEY_HASH_START; i <
|
|
98
|
-
destinationAddress[i - PUBKEY_HASH_START] = outputScript[i];
|
|
188
|
+
bytes memory destinationAddress = new bytes(HASH160_SIZE + 1);
|
|
189
|
+
for(uint8 i = PUBKEY_HASH_START; i < HASH160_SIZE + PUBKEY_HASH_START; i++) {
|
|
190
|
+
destinationAddress[i - PUBKEY_HASH_START + 1] = outputScript[i];
|
|
99
191
|
}
|
|
100
192
|
|
|
101
|
-
|
|
102
|
-
|
|
193
|
+
destinationAddress[0] = mainnet? PUBKEY_HASH_MAINNET_BYTE : PUBKEY_HASH_TESTNET_BYTE;
|
|
194
|
+
return destinationAddress;
|
|
195
|
+
}
|
|
103
196
|
|
|
104
|
-
|
|
197
|
+
/// @notice Parse a raw pay-to-script-hash output script to get the corresponding address,
|
|
198
|
+
/// the resulting byte array doesn't include the checksum bytes of the base58check encoding at
|
|
199
|
+
/// the end
|
|
200
|
+
/// @param outputScript the fragment of the raw transaction containing the raw output script
|
|
201
|
+
/// @param mainnet if the address to generate is from mainnet or testnet
|
|
202
|
+
/// @return The address generated using the script hash
|
|
203
|
+
function parsePayToScriptHash(bytes calldata outputScript, bool mainnet) public pure returns (bytes memory) {
|
|
204
|
+
require(isP2SHOutput(outputScript), "Script hasn't the required structure");
|
|
205
|
+
|
|
206
|
+
bytes memory destinationAddress = new bytes(HASH160_SIZE + 1);
|
|
207
|
+
for(uint8 i = SCRIPT_HASH_START; i < HASH160_SIZE + SCRIPT_HASH_START; i++) {
|
|
208
|
+
destinationAddress[i - SCRIPT_HASH_START + 1] = outputScript[i];
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
destinationAddress[0] = mainnet? SCRIPT_HASH_MAINNET_BYTE : SCRIPT_HASH_TESTNET_BYTE;
|
|
212
|
+
return destinationAddress;
|
|
105
213
|
}
|
|
106
214
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
215
|
+
/// @notice Parse a raw pay-to-witness-pubkey-hash output script to get the corresponding address words,
|
|
216
|
+
/// the resulting words are only the data part of the bech32 encoding and doesn't include the HRP
|
|
217
|
+
/// @param outputScript the fragment of the raw transaction containing the raw output script
|
|
218
|
+
/// @return The address bech32 words generated using the pubkey hash
|
|
219
|
+
function parsePayToWitnessPubKeyHash(bytes calldata outputScript) public pure returns (bytes memory) {
|
|
220
|
+
require(isP2WPKHOutput(outputScript), "Script hasn't the required structure");
|
|
221
|
+
uint length = 1 + total5BitWords(HASH160_SIZE);
|
|
222
|
+
bytes memory result = new bytes(length);
|
|
223
|
+
result[0] = WITNESS_VERSION_0;
|
|
224
|
+
bytes memory words = to5BitWords(outputScript[2:]);
|
|
225
|
+
for (uint i = 1; i < length; i++) {
|
|
226
|
+
result[i] = words[i - 1];
|
|
227
|
+
}
|
|
228
|
+
return result;
|
|
229
|
+
}
|
|
110
230
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
231
|
+
/// @notice Parse a raw pay-to-witness-script-hash output script to get the corresponding address words,
|
|
232
|
+
/// the resulting words are only the data part of the bech32 encoding and doesn't include the HRP
|
|
233
|
+
/// @param outputScript the fragment of the raw transaction containing the raw output script
|
|
234
|
+
/// @return The address bech32 words generated using the script hash
|
|
235
|
+
function parsePayToWitnessScriptHash(bytes calldata outputScript) public pure returns (bytes memory) {
|
|
236
|
+
require(isP2WSHOutput(outputScript), "Script hasn't the required structure");
|
|
237
|
+
uint length = 1 + total5BitWords(SHA256_SIZE);
|
|
238
|
+
bytes memory result = new bytes(length);
|
|
239
|
+
result[0] = WITNESS_VERSION_0;
|
|
240
|
+
bytes memory words = to5BitWords(outputScript[2:]);
|
|
241
|
+
for (uint i = 1; i < length; i++) {
|
|
242
|
+
result[i] = words[i - 1];
|
|
114
243
|
}
|
|
244
|
+
return result;
|
|
245
|
+
}
|
|
115
246
|
|
|
116
|
-
|
|
247
|
+
/// @notice Parse a raw pay-to-taproot output script to get the corresponding address words,
|
|
248
|
+
/// the resulting words are only the data part of the bech32m encoding and doesn't include the HRP
|
|
249
|
+
/// @param outputScript the fragment of the raw transaction containing the raw output script
|
|
250
|
+
/// @return The address bech32m words generated using the taproot pubkey hash
|
|
251
|
+
function parsePayToTaproot(bytes calldata outputScript) public pure returns (bytes memory) {
|
|
252
|
+
require(isP2TROutput(outputScript), "Script hasn't the required structure");
|
|
253
|
+
uint length = 1 + total5BitWords(TAPROOT_PUBKEY_SIZE);
|
|
254
|
+
bytes memory result = new bytes(length);
|
|
255
|
+
result[0] = WITNESS_VERSION_1;
|
|
256
|
+
bytes memory words = to5BitWords(outputScript[2:]);
|
|
257
|
+
for (uint i = 1; i < length; i++) {
|
|
258
|
+
result[i] = words[i - 1];
|
|
259
|
+
}
|
|
260
|
+
return result;
|
|
117
261
|
}
|
|
118
262
|
|
|
119
263
|
/// @notice Parse a raw null-data output script to get its content
|
|
@@ -121,7 +265,7 @@ library BtcUtils {
|
|
|
121
265
|
/// @return The content embedded inside the script
|
|
122
266
|
function parseNullDataScript(bytes calldata outputScript) public pure returns (bytes memory) {
|
|
123
267
|
require(outputScript.length > 1,"Invalid size");
|
|
124
|
-
require(outputScript[0] ==
|
|
268
|
+
require(outputScript[0] == OpCodes.OP_RETURN, "Not OP_RETURN");
|
|
125
269
|
return outputScript[1:];
|
|
126
270
|
}
|
|
127
271
|
|
|
@@ -165,7 +309,8 @@ library BtcUtils {
|
|
|
165
309
|
(uint32(uint8(bs[offset + 3])) << 24);
|
|
166
310
|
}
|
|
167
311
|
|
|
168
|
-
/// @notice Check if a pay-to-script-hash address belogs to a specific script
|
|
312
|
+
/// @notice Check if a pay-to-script-hash address belogs to a specific script, expects the address
|
|
313
|
+
/// bytes to include the 4 checksum bytes at the end
|
|
169
314
|
/// @param p2sh the pay-to-script-hash address
|
|
170
315
|
/// @param script the script to check
|
|
171
316
|
/// @param mainnet flag to specify if its a mainnet address
|
|
@@ -174,14 +319,15 @@ library BtcUtils {
|
|
|
174
319
|
return p2sh.length == 25 && keccak256(p2sh) == keccak256(getP2SHAddressFromScript(script, mainnet));
|
|
175
320
|
}
|
|
176
321
|
|
|
177
|
-
/// @notice Generate a pay-to-script-hash address from a script
|
|
322
|
+
/// @notice Generate a pay-to-script-hash address from a script, the resulting byte array already contains
|
|
323
|
+
/// the 4 checksum bytes at the end of it
|
|
178
324
|
/// @param script the script to generate the address from
|
|
179
325
|
/// @param mainnet flag to specify if the output should be a mainnet address
|
|
180
326
|
/// @return The address generate from the script
|
|
181
327
|
function getP2SHAddressFromScript(bytes calldata script, bool mainnet) public pure returns (bytes memory) {
|
|
182
328
|
bytes20 scriptHash = ripemd160(abi.encodePacked(sha256(script)));
|
|
183
|
-
|
|
184
|
-
bytes memory versionAndHash = bytes.concat(
|
|
329
|
+
bytes1 versionByte = mainnet ? SCRIPT_HASH_MAINNET_BYTE : SCRIPT_HASH_TESTNET_BYTE;
|
|
330
|
+
bytes memory versionAndHash = bytes.concat(versionByte, scriptHash);
|
|
185
331
|
bytes4 checksum = bytes4(sha256(abi.encodePacked(sha256(versionAndHash))));
|
|
186
332
|
return bytes.concat(versionAndHash, checksum);
|
|
187
333
|
}
|
|
@@ -220,4 +366,36 @@ library BtcUtils {
|
|
|
220
366
|
}
|
|
221
367
|
return result;
|
|
222
368
|
}
|
|
369
|
+
|
|
370
|
+
/// @notice Referece for implementation: https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki
|
|
371
|
+
function to5BitWords(bytes memory byteArray) private pure returns(bytes memory) {
|
|
372
|
+
uint8 MAX_VALUE = 31;
|
|
373
|
+
|
|
374
|
+
uint currentValue = 0;
|
|
375
|
+
uint bitCount = 0;
|
|
376
|
+
uint8 resultIndex = 0;
|
|
377
|
+
bytes memory result = new bytes(total5BitWords(byteArray.length));
|
|
378
|
+
|
|
379
|
+
for (uint i = 0; i < byteArray.length; ++i) {
|
|
380
|
+
currentValue = (currentValue << BYTE_SIZE) | uint8(byteArray[i]);
|
|
381
|
+
bitCount += BYTE_SIZE;
|
|
382
|
+
while (bitCount >= BECH32_WORD_SIZE) {
|
|
383
|
+
bitCount -= BECH32_WORD_SIZE;
|
|
384
|
+
// this mask ensures that the result will always have 5 bits
|
|
385
|
+
result[resultIndex] = bytes1(uint8((currentValue >> bitCount) & MAX_VALUE));
|
|
386
|
+
resultIndex++;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
if (bitCount > 0) {
|
|
391
|
+
result[resultIndex] = bytes1(uint8((currentValue << (BECH32_WORD_SIZE - bitCount)) & MAX_VALUE));
|
|
392
|
+
}
|
|
393
|
+
return result;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
function total5BitWords(uint numberOfBytes) private pure returns(uint) {
|
|
397
|
+
uint total = (numberOfBytes * BYTE_SIZE) / BECH32_WORD_SIZE;
|
|
398
|
+
bool extraWord = (numberOfBytes * BYTE_SIZE) % BECH32_WORD_SIZE == 0;
|
|
399
|
+
return total + (extraWord? 0 : 1);
|
|
400
|
+
}
|
|
223
401
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.18;
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
library OpCodes {
|
|
6
|
+
bytes1 public constant OP_DUP = 0x76;
|
|
7
|
+
bytes1 public constant OP_HASH160 = 0xa9;
|
|
8
|
+
bytes1 public constant OP_EQUALVERIFY = 0x88;
|
|
9
|
+
bytes1 public constant OP_CHECKSIG = 0xac;
|
|
10
|
+
bytes1 public constant OP_RETURN = 0x6a;
|
|
11
|
+
bytes1 public constant OP_EQUAL = 0x87;
|
|
12
|
+
|
|
13
|
+
bytes1 public constant OP_0 = 0x00;
|
|
14
|
+
bytes1 public constant OP_1 = 0x51;
|
|
15
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rsksmart/btc-transaction-solidity-helper",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Solidity library with functions to work with Bitcoin transactions inside smart contracts",
|
|
5
5
|
"main": "contracts",
|
|
6
6
|
"files": [
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"test:coverage": "npx hardhat coverage",
|
|
12
12
|
"lint": "npx hardhat check",
|
|
13
13
|
"compile": "npx hardhat compile",
|
|
14
|
-
"prepare": "
|
|
14
|
+
"prepare": "pip3 install pre-commit && pre-commit install"
|
|
15
15
|
},
|
|
16
16
|
"repository": {
|
|
17
17
|
"type": "git",
|
|
@@ -37,7 +37,9 @@
|
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@nomicfoundation/hardhat-toolbox": "^3.0.0",
|
|
39
39
|
"@nomiclabs/hardhat-solhint": "^3.0.1",
|
|
40
|
+
"bech32": "^2.0.0",
|
|
41
|
+
"bs58check": "^3.0.1",
|
|
40
42
|
"hardhat": "^2.17.0",
|
|
41
|
-
"
|
|
43
|
+
"solidity-coverage": "^0.8.12"
|
|
42
44
|
}
|
|
43
45
|
}
|