@rsksmart/btc-transaction-solidity-helper 0.2.1 → 0.3.0
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 +179 -0
- package/contracts/BtcUtils.sol +15 -50
- package/contracts/OpCodes.sol +3 -0
- package/package.json +1 -1
- package/Readme.md +0 -33
package/README.md
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
[](https://scorecard.dev/viewer/?uri=github.com/rsksmart/btc-transaction-solidity-helper)
|
|
2
|
+
<img src="img/rootstock-docs.png" alt="RSK Logo" style="width:100%; height: auto;" />
|
|
3
|
+
|
|
4
|
+
# BTC Transaction Solidity Helper
|
|
5
|
+
|
|
6
|
+
Bitcoin, a decentralized digital currency, serves as both a store of value and a means of transferring wealth. Its security is rooted in the blockchain, a distributed ledger maintained by a network of miners. These miners expend significant computational power and energy to create new blocks, which are added to the blockchain every 10 minutes. The more hashing power contributed by miners, the more secure the network becomes. [Learn more about Bitcoin](https://developer.bitcoin.org/index.html).
|
|
7
|
+
|
|
8
|
+
Rootstock, the pioneering open-source smart contract platform built on Bitcoin, aims to enhance the Bitcoin ecosystem by introducing smart contract functionality, near-instant payments, and improved scalability. Its comprehensive technology stack, encompassing Rootstock smart contracts and the Rootstock Infrastructure Framework, is designed to foster a more equitable and inclusive financial system. Read more about the [Rootstock Stack](/concepts/fundamentals/stack/).
|
|
9
|
+
|
|
10
|
+
The [Bitcoin Solidity helper library](https://github.com/rsksmart/btc-transaction-solidity-helper) facilitates seamless interaction between Bitcoin transactions and Solidity smart contracts on the Rootstock platform. In this guide, we will learn how to handle Bitcoin transactions in a Solidity Smart contract, we will also learn how to parse transactions, hash transactions and validate scripts for bitcoin transactions. You can find the public repository for the [bitcoin transaction solidity helper library](https://github.com/rsksmart/btc-transaction-solidity-helper).
|
|
11
|
+
|
|
12
|
+
## Features of the Library
|
|
13
|
+
|
|
14
|
+
The features of the Bitcoin Solidity Helper library include:
|
|
15
|
+
1. Bitcoin transaction output parsing: This accurately extracts and organizes transaction outputs from raw Bitcoin transactions. It is able to receive a raw tx and return an array of structures with the tx outputs.
|
|
16
|
+
2. Bitcoin transaction hashing: This calculates the cryptographic hash of a Bitcoin transaction, ensuring its authenticity and integrity. It receives a raw tx and returns its hash.
|
|
17
|
+
3. Bitcoin transaction output script validation: This verifies the validity and type of output scripts within a Bitcoin transaction, allowing for specific data extraction. It receives a raw output script, validates that it is from a specific type and returns a result. E.g. receive a raw null-data script and return the embedded data in it.
|
|
18
|
+
4. 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.
|
|
19
|
+
5. Bitcoin address validation: This checks if a Bitcoin address conforms to a particular type or format. It validates if a Bitcoin address is of a given type or not.
|
|
20
|
+
|
|
21
|
+
## Versioning
|
|
22
|
+
Current version is 
|
|
23
|
+
|
|
24
|
+
To check the NPM package, please check [Bitcoin Solidity Helper NPM Package.](https://www.npmjs.com/.package/@rsksmart/btc-transaction-solidity-helper)
|
|
25
|
+
|
|
26
|
+
## Prerequisites
|
|
27
|
+
* Knowledge of Solidity and how to write smart contracts.
|
|
28
|
+
* [Bitcoin Solidity Helper Package.](https://github.com/rsksmart/btc-transaction-solidity-helper/pkgs/npm/btc-transaction-solidity-helper)
|
|
29
|
+
|
|
30
|
+
## Setup
|
|
31
|
+
To setup the Solidity helper library in your project, run the following npm command:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install @rsksmart/btc-transaction-solidity-helper
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
### Import the library:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
import "@rsksmart/btc-transaction-solidity-helper/contracts/BtcUtils.sol";
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Using the library:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
BtcUtils.TxRawOutput[] memory outputs = BtcUtils.getOutputs(btcTx);
|
|
49
|
+
bytes memory scriptData = BtcUtils.parseNullDataScript(outputs[0].pkScript);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
_This fragment parses a raw Bitcoin transaction to extract its outputs and then parses the first output to get the data of the null data script._
|
|
53
|
+
|
|
54
|
+
## Parsing a Bitcoin Transaction Output
|
|
55
|
+
All the bitcoin transactions have a specific format when they are serialized. By having knowledge of this format, we can process a raw transaction in order to extract the information about its outputs.
|
|
56
|
+
|
|
57
|
+
A raw transaction has the following top-level format:
|
|
58
|
+
|
|
59
|
+
| Bytes | Name | Data Type | Description |
|
|
60
|
+
| --- | --- | --- | --- |
|
|
61
|
+
| 4 | Version | `int32_t` | [Transaction version number](https://developer.bitcoin.org/terms.html#term-transaction-version-number) (note, this is signed); currently version 1 or 2. Programs creating transactions using newer consensus rules may use higher version numbers. Version 2 means that [BIP68](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki#specification) applies. |
|
|
62
|
+
| Varies | tx_in count | compactSize uint | Number of inputs in this transaction. |
|
|
63
|
+
| Varies | tx_in | txIn | Transaction inputs. See description of txIn below. |
|
|
64
|
+
| Varies | tx_out count | compactSize uint | Number of outputs in this transaction. |
|
|
65
|
+
| Varies | tx_out | txOut | Transaction outputs. See description of txOut below. |
|
|
66
|
+
| 4 | lock_time | `uint32_t` | A time ([Unix epoch time](https://en.wikipedia.org/wiki/Unix_time)) or block number. See the [locktime parsing rules](https://developer.bitcoin.org/devguide/transactions.html#locktime_parsing_rules). |
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
> See the [Reference Implementation](https://developer.bitcoin.org/reference/transactions.html#raw-transaction-format)
|
|
70
|
+
|
|
71
|
+
The approach that the library takes is to calculate, based on the length of each section, where does the output part start. After this, it starts parsing each output separately and adding its script and value into a solidity data structure.
|
|
72
|
+
|
|
73
|
+
| Bytes | Name | Data Type | Description |
|
|
74
|
+
| --- | --- | --- | --- |
|
|
75
|
+
| 8 | Value | `int64_t` | Number of satoshis to spend. May be zero; the sum of all outputs may not exceed the sum of satoshis previously spent to the outpoints provided in the input section. (Exception: coinbase transactions spend the block subsidy and collect transaction fees.) |
|
|
76
|
+
| 1+ | pk_script bytes | compactSize uint | Number of bytes in the pubkey script. Maximum is 10,000 bytes. |
|
|
77
|
+
| 1+ | pk_script | `char[]` | Defines the conditions which must be satisfied to spend this output. |
|
|
78
|
+
|
|
79
|
+
> See the [Reference Implementation](https://developer.bitcoin.org/reference/transactions.html#txout-a-transaction-output)
|
|
80
|
+
|
|
81
|
+
```solidity
|
|
82
|
+
struct TxRawOutput {
|
|
83
|
+
uint64 value;
|
|
84
|
+
bytes pkScript;
|
|
85
|
+
uint256 scriptSize;
|
|
86
|
+
uint256 totalSize;
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
After finishing the processing of each output, the library returns an ordered output array, so the user can take advantage of this information in its solidity contract.
|
|
91
|
+
|
|
92
|
+
In order to show the benefits of this library, we’ll use the example of the [Flyover Protocol](/developers/integrate/flyover/). In this protocol, there is a smart contract that one party uses to claim a refund, in order to claim this refund, they need to prove that there was a payment with a specific amount done to a specific address in the Bitcoin Network, in order to do this, the smart contract receives the Bitcoin raw transaction. Since making this validation is not a trivial process, as it requires to parse the whole transaction, here is where we can see the utility of the library.
|
|
93
|
+
|
|
94
|
+
The usage of the output parsing functionality is the following:
|
|
95
|
+
```solidity
|
|
96
|
+
BtcUtils.TxRawOutput[] memory outputs = BtcUtils.getOutputs(btcTx);
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Then the user is able to perform any validation:
|
|
100
|
+
```solidity
|
|
101
|
+
require(expectedValue <= outputs[0].value, "incorrect amount");
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
:::info[Info]
|
|
105
|
+
The value field of the output structure is in satoshis.
|
|
106
|
+
:::
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
## Hashing Transactions
|
|
110
|
+
The hash algorithm used in the Bitcoin Network is just the `SHA256(SHA256())` of the serialized transaction. The library exposes one function that will apply this hash algorithm to any byte array passed to it, making it easy to calculate the transaction id of any raw transaction present in the contract.
|
|
111
|
+
|
|
112
|
+
This function is specifically useful to interact with the [rootstock native bridge](/concepts/powpeg/), as many of its functions have a transaction id as parameter. For example, by using the transaction hash function, it is easy to know how many confirmations a Bitcoin block has inside a smart contract function.
|
|
113
|
+
|
|
114
|
+
### Example code with explanation
|
|
115
|
+
Based on the example stated in the previous section, after validating that a specific transaction has an output paying a certain amount to an address. We need to know if that transaction has enough confirmations:
|
|
116
|
+
|
|
117
|
+
Here's an example:
|
|
118
|
+
|
|
119
|
+
```solidity
|
|
120
|
+
BtcUtils.TxRawOutput[] memory outputs = BtcUtils.getOutputs(btcTx);
|
|
121
|
+
require(expectedValue <= outputs[0].value, "incorrect amount");
|
|
122
|
+
bytes32 txId = BtcUtils.hashBtcTx(btcTx)
|
|
123
|
+
// assuming btcBlockHeaderHash,partialMerkleTree, merkleBranchHashes
|
|
124
|
+
// were provided in the function parameters
|
|
125
|
+
uint confirmations = bridge.getBtcTransactionConfirmations(
|
|
126
|
+
txId,
|
|
127
|
+
btcBlockHeaderHash,
|
|
128
|
+
partialMerkleTree,
|
|
129
|
+
merkleBranchHashes
|
|
130
|
+
)
|
|
131
|
+
require(confirmations > expectedConfirmations, "not enough confirmations");
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Read more about the [bridge functionality.](https://github.com/rsksmart/rskj/blob/master/rskj-core/src/main/java/co/rsk/peg/BridgeSupport.java)
|
|
135
|
+
|
|
136
|
+
## Script Validation for Bitcoin Transaction Output
|
|
137
|
+
In the Bitcoin network, when a user wants to send funds to another, the user creates a transaction and adds an output with the value that it wants to send. The other user doesn’t “receive” this amount directly, instead, we call receiving to the ability of providing the proper input to the output script so it returns `true`:
|
|
138
|
+
|
|
139
|
+
<Quote caption="Bitcoin Script Documentation">
|
|
140
|
+
|
|
141
|
+
A transaction is valid if nothing in the combined script triggers failure and the top stack item is True (non-zero) when the script exits. Read more info in [Bitcoin Script](https://en.bitcoin.it/wiki/Script)
|
|
142
|
+
</Quote>
|
|
143
|
+
|
|
144
|
+
> By having knowledge of the structure of the outputs that each type of address has, we can process and validate any arbitrary output extracted with the functions explained in the previous sections. In the same way, we can parse those outputs to obtain the specific value that later is encoded (in base58check, bech32 or bech32m) and presented as the “destination address”.
|
|
145
|
+
|
|
146
|
+
The output that the library supports and is able to parse to an address are:
|
|
147
|
+
* P2PKH (Pay to public key hash)
|
|
148
|
+
* P2SH (Pay to script hash)
|
|
149
|
+
* P2WPKH (Pay to witness public key hash)
|
|
150
|
+
* P2WSH (Pay to witness script hash)
|
|
151
|
+
* P2TR (Pay to taproot)
|
|
152
|
+
|
|
153
|
+
**Some use cases for script validation:**
|
|
154
|
+
|
|
155
|
+
As seen in the previous example, we validated inside our smart contract that a Bitcoin transaction has the correct amount and enough confirmations, now we need to validate that it was performed on the correct address. To do this, the library has the capability of parsing an arbitrary output and converting it into an address.
|
|
156
|
+
|
|
157
|
+
Here's an example:
|
|
158
|
+
|
|
159
|
+
```solidity
|
|
160
|
+
bytes memory btcTxDestination = BtcUtils.outputScriptToAddress(
|
|
161
|
+
outputs[0].pkScript,
|
|
162
|
+
mainnetFlag
|
|
163
|
+
);
|
|
164
|
+
require(keccak256(expectedAddress) == keccak256(btcTxDestination), "incorrect address");
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Conclusion
|
|
168
|
+
Congratulations, we have successfully learnt how to use the Solidity Helper library to parse, hash, and validate scripts within Bitcoin transactions. By using this library, developers can gain valuable insights into Bitcoin transaction data and build more sophisticated smart contract dApps on Rootstock.
|
|
169
|
+
|
|
170
|
+
### Future features
|
|
171
|
+
**Some future enhancements to the library includes:**
|
|
172
|
+
* Transaction Input Parsing: The ability to extract and analyze transaction input data to receive a raw tx and return an array of structs with the tx inputs.
|
|
173
|
+
* Transaction Creation: Utilities to facilitate the creation of raw Bitcoin transactions within smart contracts.
|
|
174
|
+
|
|
175
|
+
## Contribution Guidelines
|
|
176
|
+
* Please refer to the Rootstock Contribution Guidelines for more information on how to contribute to this project.
|
|
177
|
+
|
|
178
|
+
## License:
|
|
179
|
+
MIT License - Copyright (c) 2023 Rootstock.
|
package/contracts/BtcUtils.sol
CHANGED
|
@@ -59,7 +59,7 @@ library BtcUtils {
|
|
|
59
59
|
if (rawTx[4] == 0x00 && rawTx[5] == 0x01) { // if its segwit, skip marker and flag
|
|
60
60
|
currentPosition = 6;
|
|
61
61
|
}
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
(uint64 inputCount, uint16 inputCountSize) = parseCompactSizeInt(currentPosition, rawTx);
|
|
64
64
|
currentPosition += inputCountSize;
|
|
65
65
|
|
|
@@ -167,7 +167,7 @@ library BtcUtils {
|
|
|
167
167
|
}
|
|
168
168
|
|
|
169
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
|
|
170
|
+
/// @notice Reference for implementation: https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki
|
|
171
171
|
/// @param pkScript the fragment of the raw transaction containing the raw output script
|
|
172
172
|
/// @return Whether the script has a pay-to-taproot output structure or not
|
|
173
173
|
function isP2TROutput(bytes memory pkScript) public pure returns (bool) {
|
|
@@ -180,7 +180,7 @@ library BtcUtils {
|
|
|
180
180
|
/// the resulting byte array doesn't include the checksum bytes of the base58check encoding at
|
|
181
181
|
/// the end
|
|
182
182
|
/// @param outputScript the fragment of the raw transaction containing the raw output script
|
|
183
|
-
/// @param mainnet if the address to generate is from mainnet or testnet
|
|
183
|
+
/// @param mainnet if the address to generate is from mainnet or testnet
|
|
184
184
|
/// @return The address generated using the receiver's public key hash
|
|
185
185
|
function parsePayToPubKeyHash(bytes calldata outputScript, bool mainnet) public pure returns (bytes memory) {
|
|
186
186
|
require(isP2PKHOutput(outputScript), "Script hasn't the required structure");
|
|
@@ -217,13 +217,12 @@ library BtcUtils {
|
|
|
217
217
|
/// @param outputScript the fragment of the raw transaction containing the raw output script
|
|
218
218
|
/// @return The address bech32 words generated using the pubkey hash
|
|
219
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 +
|
|
220
|
+
require(isP2WPKHOutput(outputScript), "Script hasn't the required structure");
|
|
221
|
+
uint length = 1 + HASH160_SIZE;
|
|
222
222
|
bytes memory result = new bytes(length);
|
|
223
223
|
result[0] = WITNESS_VERSION_0;
|
|
224
|
-
bytes memory words = to5BitWords(outputScript[2:]);
|
|
225
224
|
for (uint i = 1; i < length; i++) {
|
|
226
|
-
result[i] =
|
|
225
|
+
result[i] = outputScript[i + 1];
|
|
227
226
|
}
|
|
228
227
|
return result;
|
|
229
228
|
}
|
|
@@ -234,12 +233,11 @@ library BtcUtils {
|
|
|
234
233
|
/// @return The address bech32 words generated using the script hash
|
|
235
234
|
function parsePayToWitnessScriptHash(bytes calldata outputScript) public pure returns (bytes memory) {
|
|
236
235
|
require(isP2WSHOutput(outputScript), "Script hasn't the required structure");
|
|
237
|
-
uint length = 1 +
|
|
236
|
+
uint length = 1 + SHA256_SIZE;
|
|
238
237
|
bytes memory result = new bytes(length);
|
|
239
238
|
result[0] = WITNESS_VERSION_0;
|
|
240
|
-
bytes memory words = to5BitWords(outputScript[2:]);
|
|
241
239
|
for (uint i = 1; i < length; i++) {
|
|
242
|
-
result[i] =
|
|
240
|
+
result[i] = outputScript[i + 1];
|
|
243
241
|
}
|
|
244
242
|
return result;
|
|
245
243
|
}
|
|
@@ -250,18 +248,17 @@ library BtcUtils {
|
|
|
250
248
|
/// @return The address bech32m words generated using the taproot pubkey hash
|
|
251
249
|
function parsePayToTaproot(bytes calldata outputScript) public pure returns (bytes memory) {
|
|
252
250
|
require(isP2TROutput(outputScript), "Script hasn't the required structure");
|
|
253
|
-
uint length = 1 +
|
|
251
|
+
uint length = 1 + TAPROOT_PUBKEY_SIZE;
|
|
254
252
|
bytes memory result = new bytes(length);
|
|
255
253
|
result[0] = WITNESS_VERSION_1;
|
|
256
|
-
bytes memory words = to5BitWords(outputScript[2:]);
|
|
257
254
|
for (uint i = 1; i < length; i++) {
|
|
258
|
-
result[i] =
|
|
255
|
+
result[i] = outputScript[i + 1];
|
|
259
256
|
}
|
|
260
257
|
return result;
|
|
261
258
|
}
|
|
262
259
|
|
|
263
260
|
/// @notice Parse a raw null-data output script to get its content
|
|
264
|
-
/// @param outputScript the fragment of the raw transaction containing the raw output script
|
|
261
|
+
/// @param outputScript the fragment of the raw transaction containing the raw output script
|
|
265
262
|
/// @return The content embedded inside the script
|
|
266
263
|
function parseNullDataScript(bytes calldata outputScript) public pure returns (bytes memory) {
|
|
267
264
|
require(outputScript.length > 1,"Invalid size");
|
|
@@ -271,7 +268,7 @@ library BtcUtils {
|
|
|
271
268
|
|
|
272
269
|
/// @notice Hash a bitcoin raw transaction to get its id (reversed double sha256)
|
|
273
270
|
/// @param btcTx the transaction to hash
|
|
274
|
-
/// @return The transaction id
|
|
271
|
+
/// @return The transaction id
|
|
275
272
|
function hashBtcTx(bytes calldata btcTx) public pure returns (bytes32) {
|
|
276
273
|
bytes memory doubleSha256 = abi.encodePacked(sha256(abi.encodePacked(sha256(btcTx))));
|
|
277
274
|
bytes1 aux;
|
|
@@ -340,7 +337,7 @@ library BtcUtils {
|
|
|
340
337
|
} else if (maxSize <= MAX_COMPACT_SIZE_LENGTH) {
|
|
341
338
|
return (maxSize, 1);
|
|
342
339
|
}
|
|
343
|
-
|
|
340
|
+
|
|
344
341
|
uint compactSizeBytes = 2 ** (maxSize - MAX_COMPACT_SIZE_LENGTH);
|
|
345
342
|
require(compactSizeBytes <= MAX_BYTES_USED_FOR_COMPACT_SIZE, "unsupported compact size length");
|
|
346
343
|
|
|
@@ -357,7 +354,7 @@ library BtcUtils {
|
|
|
357
354
|
bytes memory array
|
|
358
355
|
) private pure returns (uint) {
|
|
359
356
|
require(
|
|
360
|
-
fragmentStart < array.length && fragmentEnd < array.length,
|
|
357
|
+
fragmentStart < array.length && fragmentEnd < array.length,
|
|
361
358
|
"Range can't be bigger than array"
|
|
362
359
|
);
|
|
363
360
|
uint result = 0;
|
|
@@ -366,36 +363,4 @@ library BtcUtils {
|
|
|
366
363
|
}
|
|
367
364
|
return result;
|
|
368
365
|
}
|
|
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
|
-
}
|
|
401
|
-
}
|
|
366
|
+
}
|
package/contracts/OpCodes.sol
CHANGED
|
@@ -3,6 +3,7 @@ pragma solidity ^0.8.18;
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
library OpCodes {
|
|
6
|
+
bytes1 public constant OP_DROP = 0x75;
|
|
6
7
|
bytes1 public constant OP_DUP = 0x76;
|
|
7
8
|
bytes1 public constant OP_HASH160 = 0xa9;
|
|
8
9
|
bytes1 public constant OP_EQUALVERIFY = 0x88;
|
|
@@ -10,6 +11,8 @@ library OpCodes {
|
|
|
10
11
|
bytes1 public constant OP_RETURN = 0x6a;
|
|
11
12
|
bytes1 public constant OP_EQUAL = 0x87;
|
|
12
13
|
|
|
14
|
+
bytes1 public constant OP_PUSHBYTES_32 = 0x20;
|
|
15
|
+
|
|
13
16
|
bytes1 public constant OP_0 = 0x00;
|
|
14
17
|
bytes1 public constant OP_1 = 0x51;
|
|
15
18
|
}
|
package/package.json
CHANGED
package/Readme.md
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# Bitcoin Transaction Solidity Helper
|
|
2
|
-
[](https://scorecard.dev/viewer/?uri=github.com/rsksmart/btc-transaction-solidity-helper)
|
|
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.
|
|
5
|
-
|
|
6
|
-
## Features
|
|
7
|
-
|
|
8
|
-
The features of this library include:
|
|
9
|
-
* Bitcoin transaction output parsing: is able to receive a raw tx and return an array of structures with the tx outputs
|
|
10
|
-
* Bitcoin transaction hashing: is able to receive a raw tx and return its hash
|
|
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
|
|
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.
|
|
14
|
-
|
|
15
|
-
### Future features
|
|
16
|
-
These are some features that can increase the library capabilities in the future:
|
|
17
|
-
* Bitcoin transaction input parsing: should be able to receive a raw tx and return an array of structs with the tx inputs
|
|
18
|
-
* Bitcoin transaction creation: utilities for building a raw transaction inside a contract
|
|
19
|
-
|
|
20
|
-
## Usage
|
|
21
|
-
1. Run this command to install the contracts
|
|
22
|
-
```console
|
|
23
|
-
npm install @rsksmart/btc-transaction-solidity-helper
|
|
24
|
-
```
|
|
25
|
-
2. Import the library in your contract
|
|
26
|
-
```solidity
|
|
27
|
-
import "@rsksmart/btc-transaction-solidity-helper/contracts/BtcUtils.sol";
|
|
28
|
-
```
|
|
29
|
-
3. Use the library. E.g.:
|
|
30
|
-
```solidity
|
|
31
|
-
BtcUtils.TxRawOutput[] memory outputs = BtcUtils.getOutputs(btcTx);
|
|
32
|
-
bytes memory btcTxDestination = BtcUtils.parseNullDataScript(outputs[0].pkScript, false);
|
|
33
|
-
```
|