smartledger-bsv 3.1.0 → 3.2.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/CHANGELOG.md +123 -1
- package/README.md +233 -277
- package/bsv.bundle.js +39 -0
- package/bsv.min.js +8 -8
- package/docs/ADVANCED_COVENANT_DEVELOPMENT.md +533 -0
- package/docs/COVENANT_DEVELOPMENT_RESOLVED.md +169 -0
- package/docs/CUSTOM_SCRIPT_DEVELOPMENT.md +320 -0
- package/docs/README.md +201 -0
- package/docs/block.md +46 -0
- package/docs/ecies.md +102 -0
- package/docs/index.md +104 -0
- package/docs/nchain.md +958 -0
- package/docs/networks.md +55 -0
- package/docs/preimage.md +126 -0
- package/docs/script.md +139 -0
- package/docs/transaction.md +174 -0
- package/docs/unspentoutput.md +32 -0
- package/examples/README.md +200 -0
- package/examples/basic/transaction-creation.js +534 -0
- package/examples/basic/transaction_signature_api_gap.js +178 -0
- package/examples/covenants/advanced_covenant_demo.js +219 -0
- package/examples/covenants/covenant_interface_demo.js +270 -0
- package/examples/covenants/covenant_manual_signature_resolved.js +212 -0
- package/examples/covenants/covenant_signature_template.js +117 -0
- package/examples/covenants2/covenant_bidirectional_example.js +262 -0
- package/examples/covenants2/covenant_utils_demo.js +120 -0
- package/examples/covenants2/preimage_covenant_utils.js +287 -0
- package/examples/covenants2/production_integration.js +256 -0
- package/examples/data/covenant_utxos.json +28 -0
- package/examples/data/utxos.json +26 -0
- package/examples/preimage/README.md +178 -0
- package/examples/preimage/extract_preimage_bidirectional.js +421 -0
- package/examples/preimage/generate_sample_preimage.js +208 -0
- package/examples/preimage/generate_sighash_examples.js +152 -0
- package/examples/preimage/parse_preimage.js +117 -0
- package/examples/preimage/test_preimage_extractor.js +53 -0
- package/examples/preimage/test_varint_extraction.js +95 -0
- package/examples/scripts/custom_script_helper_example.js +273 -0
- package/examples/scripts/custom_script_signature_test.js +344 -0
- package/examples/scripts/script_interpreter.js +193 -0
- package/examples/smart_contract/complete_workflow_demo.js +343 -0
- package/examples/smart_contract/covenant_builder_demo.js +176 -0
- package/examples/smart_contract/script_testing_integration.js +198 -0
- package/index.js +3 -0
- package/lib/covenant-interface.js +713 -0
- package/lib/opcode.js +14 -7
- package/lib/smart_contract/API_REFERENCE.md +754 -0
- package/lib/smart_contract/DOCUMENTATION_SUMMARY.md +201 -0
- package/lib/smart_contract/EXAMPLES.md +751 -0
- package/lib/smart_contract/QUICK_START.md +549 -0
- package/lib/smart_contract/README.md +395 -0
- package/lib/smart_contract/builder.js +452 -0
- package/lib/smart_contract/covenant.js +336 -0
- package/lib/smart_contract/covenant_builder.js +512 -0
- package/lib/smart_contract/index.js +311 -0
- package/lib/smart_contract/opcode_list.js +30 -0
- package/lib/smart_contract/opcode_map.js +1174 -0
- package/lib/smart_contract/opcodes.md +1173 -0
- package/lib/smart_contract/preimage.js +903 -0
- package/lib/smart_contract/script_tester.js +487 -0
- package/lib/smart_contract/script_utils.js +609 -0
- package/lib/smart_contract/sighash.js +310 -0
- package/lib/smart_contract/smartledger-opcode_review.md +70 -0
- package/lib/smart_contract/test_integration.js +269 -0
- package/lib/smart_contract/utxo_generator.js +367 -0
- package/package.json +43 -10
- package/utilities/blockchain-state.json +20478 -3
package/docs/networks.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Networks
|
|
2
|
+
Bitcore provides support for the main bitcoin network as well as for `testnet3`, the current test blockchain. We encourage the use of `Networks.livenet` and `Networks.testnet` as constants. Note that the library sometimes may check for equality against this object. Please avoid creating a deep copy of this object.
|
|
3
|
+
|
|
4
|
+
The `Network` namespace has a function, `get(...)` that returns an instance of a `Network` or `undefined`. The only argument to this function is some kind of identifier of the network: either its name, a reference to a Network object, or a number used as a magic constant to identify the network (for example, the value `0` that gives bitcoin addresses the distinctive `'1'` at its beginning on livenet, is a `0x6F` for testnet).
|
|
5
|
+
|
|
6
|
+
## Regtest
|
|
7
|
+
|
|
8
|
+
The regtest network is useful for development as it's possible to programmatically and instantly generate blocks for testing. It's currently supported as a variation of testnet. Here is an example of how to use regtest with the Bitcore Library:
|
|
9
|
+
|
|
10
|
+
```javascript
|
|
11
|
+
// Standard testnet
|
|
12
|
+
> bsv.Networks.testnet.networkMagic;
|
|
13
|
+
<Buffer 0b 11 09 07>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
```javascript
|
|
17
|
+
// Enabling testnet to use the regtest port and magicNumber
|
|
18
|
+
> bsv.Networks.enableRegtest();
|
|
19
|
+
> bsv.Networks.testnet.networkMagic;
|
|
20
|
+
<Buffer fa bf b5 da>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Setting the Default Network
|
|
24
|
+
Most projects will only need to work with one of the networks. The value of `Networks.defaultNetwork` can be set to `Networks.testnet` if the project will need to only to work on testnet (the default is `Networks.livenet`).
|
|
25
|
+
|
|
26
|
+
## Network constants
|
|
27
|
+
The functionality of testnet and livenet is mostly similar (except for some relaxed block validation rules on testnet). They differ in the constants being used for human representation of base58 encoded strings. These are sometimes referred to as "version" constants.
|
|
28
|
+
|
|
29
|
+
Take a look at this modified snippet from [networks.js](https://github.com/bitpay/bsv/blob/master/lib/networks.js)
|
|
30
|
+
|
|
31
|
+
```javascript
|
|
32
|
+
var livenet = new Network();
|
|
33
|
+
_.extend(livenet, {
|
|
34
|
+
name: 'livenet',
|
|
35
|
+
alias: 'mainnet',
|
|
36
|
+
pubkeyhash: 0x00,
|
|
37
|
+
privatekey: 0x80,
|
|
38
|
+
scripthash: 0x05,
|
|
39
|
+
xpubkey: 0x0488b21e,
|
|
40
|
+
xprivkey: 0x0488ade4,
|
|
41
|
+
port: 8333
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
var testnet = new Network();
|
|
45
|
+
_.extend(testnet, {
|
|
46
|
+
name: 'testnet',
|
|
47
|
+
alias: 'testnet',
|
|
48
|
+
pubkeyhash: 0x6f,
|
|
49
|
+
privatekey: 0xef,
|
|
50
|
+
scripthash: 0xc4,
|
|
51
|
+
xpubkey: 0x043587cf,
|
|
52
|
+
xprivkey: 0x04358394,
|
|
53
|
+
port: 18333
|
|
54
|
+
});
|
|
55
|
+
```
|
package/docs/preimage.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
Excellent — here’s the **definitive, detailed breakdown** of a **Bitcoin (BSV) sighash preimage**, field by field, based on **BIP143** (which all modern BSV libraries, including SmartLedger’s hardened bundle, follow exactly).
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# 🔍 **Bitcoin SV Sighash Preimage Structure (BIP143 / ForkID)**
|
|
6
|
+
|
|
7
|
+
The *preimage* is the exact data that gets double-SHA256 hashed before signing a transaction input with `SIGHASH_FORKID`.
|
|
8
|
+
This deterministic byte layout ensures signatures are reproducible and verifiable.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 🧩 **Overview**
|
|
13
|
+
|
|
14
|
+
| Section | Bytes | Endianness | Description | |
|
|
15
|
+
| ----------------------------- | ------------ | ------------------- | ------------------------------------------ | -------- |
|
|
16
|
+
| **1. nVersion** | 4 | Little-Endian (LE) | Transaction version field | |
|
|
17
|
+
| **2. hashPrevouts** | 32 | | SHA256d of all input outpoints | |
|
|
18
|
+
| **3. hashSequence** | 32 | | SHA256d of all input sequences | |
|
|
19
|
+
| **4. outpoint (txid + vout)** | 36 | txid: LE, index: LE | The outpoint being signed | |
|
|
20
|
+
| **5. scriptCode length** | 1–3 (varint) | | Compact size of the script being signed | |
|
|
21
|
+
| **6. scriptCode** | variable | | The actual script (usually `scriptPubKey`) | |
|
|
22
|
+
| **7. amount** | 8 | Little-Endian | Value of the output being spent | |
|
|
23
|
+
| **8. nSequence** | 4 | Little-Endian | Sequence number of this input | |
|
|
24
|
+
| **9. hashOutputs** | 32 | | SHA256d of all outputs | |
|
|
25
|
+
| **10. nLockTime** | 4 | Little-Endian | Locktime for entire tx | |
|
|
26
|
+
| **11. sighashType** | 4 | Little-Endian | SIGHASH type used (e.g., `0x41` for `ALL | FORKID`) |
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 📏 **Typical Length Example**
|
|
31
|
+
|
|
32
|
+
For a *simple single-input, single-output* transaction:
|
|
33
|
+
|
|
34
|
+
| Section | Typical Bytes | Example Hex Segment |
|
|
35
|
+
| ----------------------- | ------------- | ------------------------ |
|
|
36
|
+
| nVersion | 4 | `01000000` |
|
|
37
|
+
| hashPrevouts | 32 | `e3...4a` |
|
|
38
|
+
| hashSequence | 32 | `00...00` |
|
|
39
|
+
| outpoint | 36 | `00..00 00000000` |
|
|
40
|
+
| scriptCode (len + data) | 25 | `1976a914...88ac` |
|
|
41
|
+
| amount | 8 | `1027000000000000` |
|
|
42
|
+
| nSequence | 4 | `ffffffff` |
|
|
43
|
+
| hashOutputs | 32 | `d2...1e` |
|
|
44
|
+
| nLockTime | 4 | `e8030000` *(= 1000 LE)* |
|
|
45
|
+
| sighashType | 4 | `41000000` *(= 0x41)* |
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
### 🧮 **Total: ~108 bytes**
|
|
50
|
+
|
|
51
|
+
(4 + 32 + 32 + 36 + 25 + 8 + 4 + 32 + 4 + 4 = 181, but since script length and varints can vary,
|
|
52
|
+
the final preimage for a minimal transaction typically is **~108 bytes**.)
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## 🧠 **Endianness Notes**
|
|
57
|
+
|
|
58
|
+
* **nVersion, amount, nSequence, nLockTime, sighashType** are *little-endian* integers.
|
|
59
|
+
* **hashPrevouts, hashSequence, hashOutputs** are *big-endian* SHA256d hashes (32 bytes each).
|
|
60
|
+
* **txid** inside the *outpoint* is *little-endian* (it’s reversed from what’s printed on explorers).
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## 🧩 **Visual Layout Example**
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
[0000-0003] nVersion (4 LE)
|
|
68
|
+
[0004-0023] hashPrevouts (32)
|
|
69
|
+
[0024-0043] hashSequence (32)
|
|
70
|
+
[0044-005f] outpoint.txid (32 LE)
|
|
71
|
+
[0060-0063] outpoint.vout (4 LE)
|
|
72
|
+
[0064-007e] script length + scriptPubKey (varies)
|
|
73
|
+
[007f-0086] amount (8 LE)
|
|
74
|
+
[0087-008a] nSequence (4 LE)
|
|
75
|
+
[008b-00aa] hashOutputs (32)
|
|
76
|
+
[00ab-00ae] nLockTime (4 LE)
|
|
77
|
+
[00af-00b2] sighashType (4 LE)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## ⚙️ **In Script Context (OP_SPLIT / Covenant Use)**
|
|
83
|
+
|
|
84
|
+
If you push the **raw preimage** onto the stack, you can target sections as follows:
|
|
85
|
+
|
|
86
|
+
| Target | Extraction Logic | Example ASM |
|
|
87
|
+
| ---------------- | -------------------------------------------- | ------------------------------------------------------- |
|
|
88
|
+
| **nVersion** | First 4 bytes | `4 OP_SPLIT OP_DROP OP_BIN2NUM` |
|
|
89
|
+
| **nLockTime** | 8 bytes from end → drop last 4 (sighashType) | `<len-8> OP_SPLIT OP_NIP 4 OP_SPLIT OP_DROP OP_BIN2NUM` |
|
|
90
|
+
| **hashPrevouts** | 32 bytes after first 4 | `4 OP_SPLIT OP_DROP 32 OP_SPLIT OP_DROP` |
|
|
91
|
+
| **hashOutputs** | 8+4+32 from end (44 bytes from tail) | `<len-44> OP_SPLIT OP_NIP 32 OP_SPLIT OP_DROP` |
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 🧾 **Checksum Behavior**
|
|
96
|
+
|
|
97
|
+
The `sighashPreimage` is *never hashed directly* into the blockchain.
|
|
98
|
+
Instead:
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
signature = ECDSA.sign( sha256sha256(preimage), privKey )
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
In your covenant scripts, you typically:
|
|
105
|
+
|
|
106
|
+
1. Re-hash the preimage (`OP_HASH256`) to verify it matches what was signed.
|
|
107
|
+
2. Then you may dissect it to verify constraints (like `nLockTime`, `nVersion`, etc.).
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## ✅ **Summary Table**
|
|
112
|
+
|
|
113
|
+
| Field | Bytes | Endian | Covenant Extraction Example |
|
|
114
|
+
| ------------ | -------- | ------ | ------------------------------------------------------- |
|
|
115
|
+
| nVersion | 4 | LE | `4 OP_SPLIT OP_DROP OP_BIN2NUM` |
|
|
116
|
+
| hashPrevouts | 32 | — | `36 OP_SPLIT ...` |
|
|
117
|
+
| hashSequence | 32 | — | next 32 |
|
|
118
|
+
| outpoint | 36 | mixed | — |
|
|
119
|
+
| scriptCode | variable | — | rarely enforced directly |
|
|
120
|
+
| amount | 8 | LE | `40 OP_SPLIT OP_NIP 8 OP_SPLIT OP_DROP OP_BIN2NUM` |
|
|
121
|
+
| nSequence | 4 | LE | `12 OP_SPLIT OP_NIP 4 OP_SPLIT OP_DROP OP_BIN2NUM` |
|
|
122
|
+
| hashOutputs | 32 | — | — |
|
|
123
|
+
| nLockTime | 4 | LE | `<len-8> OP_SPLIT OP_NIP 4 OP_SPLIT OP_DROP OP_BIN2NUM` |
|
|
124
|
+
| sighashType | 4 | LE | `<len-4> OP_SPLIT OP_NIP OP_BIN2NUM` |
|
|
125
|
+
|
|
126
|
+
---
|
package/docs/script.md
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Script
|
|
2
|
+
All bitcoin transactions have scripts embedded into its inputs and outputs. The scripts use a very simple programming language, which is evaluated from left to right using a stack. The language is designed such that it guarantees all scripts will execute in a limited amount of time (it is Turing-Complete).
|
|
3
|
+
|
|
4
|
+
When a transaction is validated, the input scripts are concatenated with the output scripts and evaluated. To be valid, all transaction scripts must evaluate to true. A good analogy for how this works is that the output scripts are puzzles that specify in which conditions can those bitcoins be spent. The input scripts provide the correct data to make those output scripts evaluate to true.
|
|
5
|
+
|
|
6
|
+
For more detailed information about the bitcoin scripting language, check the online reference [on bitcoin's wiki](https://en.bitcoin.it/wiki/Script).
|
|
7
|
+
|
|
8
|
+
The `Script` object provides an interface to construct, parse, and identify bitcoin scripts. It also gives simple interfaces to create most common script types. This class is useful if you want to create custom input or output scripts. In other case, you should probably use `Transaction`.
|
|
9
|
+
|
|
10
|
+
## Script creation
|
|
11
|
+
Here's how to use `Script` to create the five most common script types:
|
|
12
|
+
|
|
13
|
+
### Pay to Public Key Hash (p2pkh)
|
|
14
|
+
This is the most commonly used transaction output script. It's used to pay to a bitcoin address (a bitcoin address is a public key hash encoded in base58check)
|
|
15
|
+
|
|
16
|
+
```javascript
|
|
17
|
+
// create a new p2pkh paying to a specific address
|
|
18
|
+
var address = Address.fromString('1NaTVwXDDUJaXDQajoa9MqHhz4uTxtgK14');
|
|
19
|
+
var script = Script.buildPublicKeyHashOut(address);
|
|
20
|
+
assert(script.toString() === 'OP_DUP OP_HASH160 20 0xecae7d092947b7ee4998e254aa48900d26d2ce1d OP_EQUALVERIFY OP_CHECKSIG');
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Pay to Public Key (p2pk)
|
|
24
|
+
Pay to public key scripts are a simplified form of the p2pkh, but aren't commonly used in new transactions anymore, because p2pkh scripts are more secure (the public key is not revealed until the output is spent).
|
|
25
|
+
|
|
26
|
+
```javascript
|
|
27
|
+
// create a new p2pk paying to a specific public key
|
|
28
|
+
var pubkey = new PublicKey('022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da');
|
|
29
|
+
var script = Script.buildPublicKeyOut(pubkey);
|
|
30
|
+
assert(script.toString() === '33 0x022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da OP_CHECKSIG');
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Pay to Multisig (p2ms)
|
|
34
|
+
Multisig outputs allow to share control of bitcoins between several keys. When creating the script, one specifies the public keys that control the funds, and how many of those keys are required to sign off spending transactions to be valid. An output with N public keys of which M are required is called an m-of-n output (For example, 2-of-3, 3-of-5, 4-of-4, etc.)
|
|
35
|
+
|
|
36
|
+
Note that regular multisig outputs are rarely used nowadays.
|
|
37
|
+
|
|
38
|
+
```javascript
|
|
39
|
+
// create a new 2-of-3 multisig output from 3 given public keys
|
|
40
|
+
var pubkeys = [
|
|
41
|
+
new PublicKey('022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da'),
|
|
42
|
+
new PublicKey('03e3818b65bcc73a7d64064106a859cc1a5a728c4345ff0b641209fba0d90de6e9'),
|
|
43
|
+
new PublicKey('021f2f6e1e50cb6a953935c3601284925decd3fd21bc445712576873fb8c6ebc18'),
|
|
44
|
+
];
|
|
45
|
+
var threshold = 2;
|
|
46
|
+
var script = Script.buildMultisigOut(pubkeys, threshold);
|
|
47
|
+
assert(script.toString() === 'OP_2 33 0x022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da'
|
|
48
|
+
+ ' 33 0x03e3818b65bcc73a7d64064106a859cc1a5a728c4345ff0b641209fba0d90de6e9'
|
|
49
|
+
+ ' 33 0x021f2f6e1e50cb6a953935c3601284925decd3fd21bc445712576873fb8c6ebc18 OP_3 OP_CHECKMULTISIG');
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Pay to Script Hash (p2sh)
|
|
53
|
+
|
|
54
|
+
DEPRECATED - Do not use p2sh on Bitcoin SV.
|
|
55
|
+
|
|
56
|
+
Pay to script hash outputs are scripts that contain the hash of another script, called `redeemScript`. To spend bitcoins sent in a p2sh output, the spending transaction must provide a script matching the script hash and data which makes the script evaluate to true. This allows to defer revealing the spending conditions to the moment of spending. It also makes it possible for the receiver to set the conditions to spend those bitcoins.
|
|
57
|
+
|
|
58
|
+
Most multisig transactions today use p2sh outputs where the `redeemScript` is a multisig output.
|
|
59
|
+
|
|
60
|
+
```javascript
|
|
61
|
+
// create a p2sh multisig output
|
|
62
|
+
var pubkeys = [
|
|
63
|
+
new PublicKey('022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da'),
|
|
64
|
+
new PublicKey('03e3818b65bcc73a7d64064106a859cc1a5a728c4345ff0b641209fba0d90de6e9'),
|
|
65
|
+
new PublicKey('021f2f6e1e50cb6a953935c3601284925decd3fd21bc445712576873fb8c6ebc18'),
|
|
66
|
+
];
|
|
67
|
+
var redeemScript = Script.buildMultisigOut(pubkeys, 2);
|
|
68
|
+
var script = redeemScript.toScriptHashOut();
|
|
69
|
+
assert(script.toString() === 'OP_HASH160 20 0x620a6eeaf538ec9eb89b6ae83f2ed8ef98566a03 OP_EQUAL');
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Data output
|
|
73
|
+
Data outputs are used to push data into the blockchain. Up to 40 bytes can be pushed in a standard way, but more data can be used, if a miner decides to accept the transaction.
|
|
74
|
+
|
|
75
|
+
```javascript
|
|
76
|
+
var data = 'hello world!!!';
|
|
77
|
+
var script = Script.buildDataOut(data);
|
|
78
|
+
assert(script.toString() === 'OP_RETURN 14 0x68656c6c6f20776f726c64212121'
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Custom Scripts
|
|
82
|
+
To create a custom `Script` instance, you must rely on the lower-level methods `add` and `prepend`. Both methods accept the same parameter types, and insert an opcode or data at the beginning (`prepend`) or end (`add`) of the `Script`.
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
var script = Script()
|
|
86
|
+
.add('OP_IF') // add an opcode by name
|
|
87
|
+
.prepend(114) // add OP_2SWAP by code
|
|
88
|
+
.add(Opcode.OP_NOT) // add an opcode object
|
|
89
|
+
.add(Buffer.from('bacacafe', 'hex')) // add a data buffer (will append the size of the push operation first)
|
|
90
|
+
|
|
91
|
+
assert(script.toString() === 'OP_2SWAP OP_IF OP_NOT 4 0xbacacafe');
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Script Parsing and Identification
|
|
95
|
+
`Script` has an easy interface to parse raw scripts from the network or bitcoind, and to extract useful information. An illustrative example (for more options check the API reference)
|
|
96
|
+
|
|
97
|
+
```javascript
|
|
98
|
+
var raw_script = Buffer.from('5221022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da2103e3818b65bcc73a7d64064106a859cc1a5a728c4345ff0b641209fba0d90de6e921021f2f6e1e50cb6a953935c3601284925decd3fd21bc445712576873fb8c6ebc1853ae', 'hex');
|
|
99
|
+
var s = new Script(raw_script);
|
|
100
|
+
console.log(s.toString());
|
|
101
|
+
// 'OP_2 33 0x022df8750480ad5b26950b25c7ba79d3e37d75f640f8e5d9bcd5b150a0f85014da 33 0x03e3818b65bcc73a7d64064106a859cc1a5a728c4345ff0b641209fba0d90de6e9 33 0x021f2f6e1e50cb6a953935c3601284925decd3fd21bc445712576873fb8c6ebc18 OP_3 OP_CHECKMULTISIG'
|
|
102
|
+
|
|
103
|
+
s.isPublicKeyHashOut() // false
|
|
104
|
+
s.isScriptHashOut() // false
|
|
105
|
+
s.isMultisigOut() // true
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Script Interpreting and Validation
|
|
109
|
+
To validate a transaction, the bitcoin network validates all of its inputs and outputs. To validate an input, the input's script is concatenated with the referenced output script, and the result is executed. If at the end of execution the stack contains a 'true' value, then the transaction is valid. You can do this in `bsv` by using the `Interpreter` class. The entry point (and probably the only interface you'll need for most applications) is the method `Interpreter#verify()`.
|
|
110
|
+
|
|
111
|
+
You can use it like this:
|
|
112
|
+
|
|
113
|
+
```javascript
|
|
114
|
+
var inputScript = Script('OP_1');
|
|
115
|
+
var outputScript = Script('OP_15 OP_ADD OP_16 OP_EQUAL');
|
|
116
|
+
|
|
117
|
+
var verified = Interpreter().verify(inputScript, outputScript);
|
|
118
|
+
// verified will be true
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Note that `verify` expects two scripts: one is the input script (scriptSig) and the other is the output script (scriptPubkey). This is because different conditions are checked for each.
|
|
122
|
+
|
|
123
|
+
It also accepts some optional parameters, assuming defaults if not provided:
|
|
124
|
+
|
|
125
|
+
```javascript
|
|
126
|
+
// first we create a transaction
|
|
127
|
+
var tx = new Transaction()
|
|
128
|
+
.from(utxo)
|
|
129
|
+
.to(toAddress, 100000)
|
|
130
|
+
.sign(privateKey);
|
|
131
|
+
|
|
132
|
+
// we then extract the signature from the first input
|
|
133
|
+
var inputIndex = 0;
|
|
134
|
+
var signature = tx.getSignatures(privateKey)[inputIndex].signature;
|
|
135
|
+
|
|
136
|
+
var scriptSig = Script.buildPublicKeyHashIn(publicKey, signature);
|
|
137
|
+
var flags = Interpreter.SCRIPT_VERIFY_P2SH | Interpreter.SCRIPT_VERIFY_STRICTENC;
|
|
138
|
+
var verified = Interpreter().verify(scriptSig, scriptPubkey, tx, inputIndex, flags);
|
|
139
|
+
```
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# Transaction
|
|
2
|
+
Bitcore provides a very simple API for creating transactions. We expect this API to be accessible for developers without knowing the working internals of bitcoin in deep detail. What follows is a small introduction to transactions with some basic knowledge required to use this API.
|
|
3
|
+
|
|
4
|
+
A Transaction contains a set of inputs and a set of outputs. Each input contains a reference to another transaction's output, and a signature that allows the value referenced in that output to be used in this transaction.
|
|
5
|
+
|
|
6
|
+
Note also that an output can be used only once. That's why there's a concept of "change address" in the bitcoin ecosystem: if an output of 10 BSV is available for me to spend, but I only need to transmit 1 BSV, I'll create a transaction with two outputs, one with 1 BSV that I want to spend, and the other with 9 BSV to a change address, so I can spend this 9 BSV with another private key that I own.
|
|
7
|
+
|
|
8
|
+
So, in order to transmit a valid transaction, you must know what other transactions on the network store outputs that have not been spent and that are available for you to spend (meaning that you have the set of keys that can validate you own those funds). The unspent outputs are usually referred to as "utxo"s.
|
|
9
|
+
|
|
10
|
+
Let's take a look at some very simple transactions:
|
|
11
|
+
|
|
12
|
+
```javascript
|
|
13
|
+
var transaction = new Transaction()
|
|
14
|
+
.from(utxos) // Feed information about what unspent outputs one can use
|
|
15
|
+
.to(address, amount) // Add an output with the given amount of satoshis
|
|
16
|
+
.change(address) // Sets up a change address where the rest of the funds will go
|
|
17
|
+
.sign(privkeySet) // Signs all the inputs it can
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
You can obtain the input and output total amounts of the transaction in satoshis by accessing the fields `inputAmount` and `outputAmount`.
|
|
21
|
+
|
|
22
|
+
Now, this could just be serialized to hexadecimal ASCII values (`transaction.serialize()`) and sent over to the bitcoind reference client.
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
bitcoin-cli sendrawtransaction <serialized transaction>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
You can also override the fee estimation with another amount, specified in satoshis:
|
|
29
|
+
|
|
30
|
+
```javascript
|
|
31
|
+
var transaction = new Transaction().fee(546); // Minimum non-dust amount
|
|
32
|
+
var transaction = new Transaction().fee(1e8); // Generous fee of 1 BSV
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Multisig Transactions
|
|
36
|
+
To send a transaction to a multisig address, the API is the same as in the above example. To spend outputs that require multiple signatures, the process needs extra information: the public keys of the signers that can unlock that output.
|
|
37
|
+
|
|
38
|
+
```javascript
|
|
39
|
+
var multiSigTx = new Transaction()
|
|
40
|
+
.from(utxo, publicKeys, threshold)
|
|
41
|
+
.change(address)
|
|
42
|
+
.sign(myKeys);
|
|
43
|
+
|
|
44
|
+
var serialized = multiSigTx.toObject();
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
This can be serialized and sent to another party, to complete with the needed signatures:
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
var multiSigTx = new Transaction(serialized)
|
|
51
|
+
.sign(anotherSetOfKeys);
|
|
52
|
+
|
|
53
|
+
assert(multiSigTx.isFullySigned());
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Also, you can just send over the signature for your private key:
|
|
57
|
+
|
|
58
|
+
```javascript
|
|
59
|
+
var multiSigTx = new Transaction()
|
|
60
|
+
.from(utxo, publicKeys, threshold)
|
|
61
|
+
.change(address);
|
|
62
|
+
|
|
63
|
+
var signature = multiSigTx.getSignatures(privateKey)[0];
|
|
64
|
+
console.log(JSON.stringify(signature));
|
|
65
|
+
console.log(signature.toObject());
|
|
66
|
+
console.log(signature.signature.toString()); // Outputs a DER signature
|
|
67
|
+
console.log(signature.sigtype);
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Transfer that over the wire, and on the other side, apply it to a transaction:
|
|
71
|
+
|
|
72
|
+
```javascript
|
|
73
|
+
assert(transaction.isValidSignature(receivedSig));
|
|
74
|
+
transaction.applySignature(receivedSig);
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Adding inputs
|
|
78
|
+
Transaction inputs are instances of either [Input](https://github.com/bitpay/bsv/tree/master/lib/transaction/input) or its subclasses. `Input` has some abstract methods, as there is no actual concept of a "signed input" in the bitcoin scripting system (just valid signatures for <tt>OP_CHECKSIG</tt> and similar opcodes). They are stored in the `input` property of `Transaction` instances.
|
|
79
|
+
|
|
80
|
+
Bitcore contains two implementations of `Input`, one for spending _Pay to Public Key Hash_ outputs (called `PublicKeyHashInput`) and another to spend _Pay to Script Hash_ outputs for which the redeem script is a Multisig script (called `MultisigScriptHashInput`).
|
|
81
|
+
|
|
82
|
+
All inputs have the following five properties:
|
|
83
|
+
- `prevTxId`: a `Buffer` with the id of the transaction with the output this input is spending
|
|
84
|
+
- `outputIndex`: a `number` the index of the output in the previous transaction
|
|
85
|
+
- `sequenceNumber`: a `number`, the sequence number, see [bitcoin's developer guide on nLockTime and the sequence number](https://bitcoin.org/en/developer-guide#locktime-and-sequence-number).
|
|
86
|
+
- `script`: the `Script` instance for this input. Usually called `scriptSig` in the bitcoin community.
|
|
87
|
+
- `output`: if available, a `Output` instance of the output associated with this input.
|
|
88
|
+
|
|
89
|
+
Both `PublicKeyHashInput` and `MultisigScriptHashInput` cache the information about signatures, even though this information could somehow be encoded in the script. Both need to have the `output` property set in order to calculate the `sighash` so signatures can be created.
|
|
90
|
+
|
|
91
|
+
Some methods related to adding inputs are:
|
|
92
|
+
- `from`: A high level interface to add an input from a UTXO. It has a series of variants:
|
|
93
|
+
- `from(utxo)`: add an input from an [Unspent Transaction Output](http://bsv.io/guide/unspentoutput.html). Currently, only P2PKH outputs are supported.
|
|
94
|
+
- `from(utxos)`: same as above, but passing in an array of Unspent Outputs.
|
|
95
|
+
- `from(utxo, publicKeys, threshold)`: add an input that spends a UTXO with a P2SH output for a Multisig script. The `publicKeys` argument is an array of public keys, and `threshold` is the number of required signatures in the Multisig script.
|
|
96
|
+
|
|
97
|
+
- `addInput`: Performs a series of checks on an input and appends it to the end of the `input` vector and updates the amount of incoming bitcoins of the transaction.
|
|
98
|
+
- `uncheckedAddInput`: adds an input to the end of the `input` vector and updates the `inputAmount` without performing any checks.
|
|
99
|
+
|
|
100
|
+
### PublicKeyHashInput
|
|
101
|
+
This input uses the `script` property to mark the input as unsigned if the script is empty.
|
|
102
|
+
|
|
103
|
+
### MultisigScriptHashInput
|
|
104
|
+
This input contains a set of signatures in a `signatures` property, and each time a signature is added, a potentially partial and/or invalid script is created. The `isFullySigned` method will only return true if all needed signatures are already added and valid. If `addSignature` is added after all need signatures are already set, an exception will be thrown.
|
|
105
|
+
|
|
106
|
+
## Signing a Transaction
|
|
107
|
+
The following methods are used to manage signatures for a transaction:
|
|
108
|
+
- `getSignatures`: takes an array of `PrivateKey` or strings from which a `PrivateKey` can be instantiated; the transaction to be signed; the kind of [signature hash to use](https://bitcoin.org/en/developer-guide#signature-hash-types). Returns an array of objects with the following properties:
|
|
109
|
+
- `signature`: an instance of [Signature](https://github.com/bitpay/bsv/blob/master/lib/crypto/signature.js)
|
|
110
|
+
- `prevTxId`: this input's `prevTxId`,
|
|
111
|
+
- `outputIndex`: this input's `outputIndex`,
|
|
112
|
+
- `inputIndex`: this input's index in the transaction
|
|
113
|
+
- `sigtype`: the "sighash", the type of transaction hash used to calculate the signature
|
|
114
|
+
- `publicKey`: a `PublicKey` of the `PrivateKey` used to create the signature
|
|
115
|
+
|
|
116
|
+
- `addSignature`: takes an element outputed by `getSignatures` and applies the signature to this input (modifies the script to include the new signature).
|
|
117
|
+
- `clearSignatures`: removes all signatures for this input
|
|
118
|
+
- `isFullySigned`: returns true if the input is fully signed
|
|
119
|
+
|
|
120
|
+
## Handling Outputs
|
|
121
|
+
Outputs can be added by:
|
|
122
|
+
- The `addOutput(output)` method, which pushes an `Output` to the end of the `outputs` property and updates the `outputAmount` field. It also clears signatures (as the hash of the transaction may have changed) and updates the change output.
|
|
123
|
+
- The `to(address, amount)` method, that adds an output with the script that corresponds to the given address. Builds an output and calls the `addOutput` method.
|
|
124
|
+
- Specifying a [change address](#Fee_calculation)
|
|
125
|
+
|
|
126
|
+
To remove all outputs, you can use `clearOutputs()`, which preserves change output configuration.
|
|
127
|
+
|
|
128
|
+
## Serialization
|
|
129
|
+
There are a series of methods used for serialization:
|
|
130
|
+
- `toObject`: Returns a plain JavaScript object with no methods and enough information to fully restore the state of this transaction. Using other serialization methods (except for `toJSON`) will cause a some information to be lost.
|
|
131
|
+
- `toJSON`: Will be called when using `JSON.stringify` to return JSON-encoded string using the output from `toObject`.
|
|
132
|
+
- `toString` or `uncheckedSerialize`: Returns an hexadecimal serialization of the transaction, in the [serialization format for bitcoin](https://bitcoin.org/en/developer-reference#raw-transaction-format).
|
|
133
|
+
- `serialize`: Does a series of checks before serializing the transaction
|
|
134
|
+
- `inspect`: Returns a string with some information about the transaction (currently a string formatted as `<Transaction 000...000>`, that only shows the serialized value of the transaction.
|
|
135
|
+
- `toBuffer`: Serializes the transaction for sending over the wire in the bitcoin network
|
|
136
|
+
- `toBufferWriter`: Uses an already existing BufferWriter to copy over the serialized transaction
|
|
137
|
+
|
|
138
|
+
## Serialization Checks
|
|
139
|
+
When serializing, the bsv library performs a series of checks. These can be disabled by providing an object to the `serialize` method with the checks that you'll like to skip.
|
|
140
|
+
- `disableLargeFees` avoids checking that the fee is no more than `Transaction.FEE_PER_KB * Transaction.FEE_SECURITY_MARGIN * size_in_kb`.
|
|
141
|
+
- `disableSmallFees` avoids checking that the fee is less than `Transaction.FEE_PER_KB * size_in_kb / Transaction.FEE_SECURITY_MARGIN`.
|
|
142
|
+
- `disableIsFullySigned` does not check if all inputs are fully signed
|
|
143
|
+
- `disableDustOutputs` does not check for dust outputs being generated
|
|
144
|
+
- `disableMoreOutputThanInput` avoids checking that the sum of the output amounts is less than or equal to the sum of the amounts for the outputs being spent in the transaction
|
|
145
|
+
|
|
146
|
+
These are the current default values in the bsv library involved on these checks:
|
|
147
|
+
- `Transaction.FEE_PER_KB`: `10000` (satoshis per kilobyte)
|
|
148
|
+
- `Transaction.FEE_SECURITY_MARGIN`: `15`
|
|
149
|
+
- `Transaction.DUST_AMOUNT`: `546` (satoshis)
|
|
150
|
+
|
|
151
|
+
## Fee calculation
|
|
152
|
+
When outputs' value don't sum up to the same amount that inputs, the difference in bitcoins goes to the miner of the block that includes this transaction. The concept of a "change address" usually is associated with this: an output with an address that can be spent by the creator of the transaction.
|
|
153
|
+
|
|
154
|
+
For this reason, some methods in the Transaction class are provided:
|
|
155
|
+
- `change(address)`: Set up the change address. This will set an internal `_changeScript` property that will store the change script associated with that address.
|
|
156
|
+
- `fee(amount)`: Sets up the exact amount of fee to pay. If no change address is provided, this will raise an exception.
|
|
157
|
+
- `getFee()`: returns the estimated fee amount to be paid, based on the size of the transaction, but disregarding the priority of the outputs.
|
|
158
|
+
|
|
159
|
+
Internally, a `_changeIndex` property stores the index of the change output (so it can get updated when a new input or output is added).
|
|
160
|
+
|
|
161
|
+
## Time-Locking transaction
|
|
162
|
+
All bitcoin transactions contain a locktime field. The locktime indicates the earliest time a transaction can be added to the blockchain. Locktime allows signers to create time-locked transactions which will only become valid in the future, giving the signers a chance to change their minds. Locktime can be set in the form of a bitcoin block height (the transaction can only be included in a block with a higher height than specified) or a linux timestamp (transaction can only be confirmed after that time). For more information see [bitcoin's development guide section on locktime](https://bitcoin.org/en/developer-guide#locktime-and-sequence-number).
|
|
163
|
+
|
|
164
|
+
In bsv, you can set a `Transaction`'s locktime by using the methods `Transaction#lockUntilDate` and `Transaction#lockUntilBlockHeight`. You can also get a friendly version of the locktime field via `Transaction#getLockTime`;
|
|
165
|
+
|
|
166
|
+
For example:
|
|
167
|
+
|
|
168
|
+
```javascript
|
|
169
|
+
var future = new Date(2025,10,30); // Sun Nov 30 2025
|
|
170
|
+
var transaction = new Transaction()
|
|
171
|
+
.lockUntilDate(future);
|
|
172
|
+
console.log(transaction.getLockTime());
|
|
173
|
+
// output similar to: Sun Nov 30 2025 00:00:00 GMT-0300 (ART)
|
|
174
|
+
```
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# UnspentOutput
|
|
2
|
+
`bsv.Transaction.UnspentOutput` is a class with stateless instances that provides information about an unspent output:
|
|
3
|
+
- Transaction ID and output index
|
|
4
|
+
- The "scriptPubKey", the script included in the output
|
|
5
|
+
- Amount of satoshis associated
|
|
6
|
+
- Address, if available
|
|
7
|
+
|
|
8
|
+
## Parameters
|
|
9
|
+
The constructor is quite permissive with the input arguments. It can take outputs straight out of bitcoind's getunspent RPC call. Some of the names are not very informative for new users, so the UnspentOutput constructor also understands these aliases:
|
|
10
|
+
- `scriptPubKey`: just `script` is also accepted
|
|
11
|
+
- `amount`: expected value in BSV. If the `satoshis` alias is used, make sure to use satoshis instead of BSV.
|
|
12
|
+
- `vout`: this is the index of the output in the transaction, renamed to `outputIndex`
|
|
13
|
+
- `txid`: `txId`
|
|
14
|
+
|
|
15
|
+
## Example
|
|
16
|
+
|
|
17
|
+
```javascript
|
|
18
|
+
var utxo = new UnspentOutput({
|
|
19
|
+
"txid" : "a0a08e397203df68392ee95b3f08b0b3b3e2401410a38d46ae0874f74846f2e9",
|
|
20
|
+
"vout" : 0,
|
|
21
|
+
"address" : "mgJT8iegL4f9NCgQFeFyfvnSw1Yj4M5Woi",
|
|
22
|
+
"scriptPubKey" : "76a914089acaba6af8b2b4fb4bed3b747ab1e4e60b496588ac",
|
|
23
|
+
"amount" : 0.00070000
|
|
24
|
+
});
|
|
25
|
+
var utxo = new UnspentOutput({
|
|
26
|
+
"txId" : "a0a08e397203df68392ee95b3f08b0b3b3e2401410a38d46ae0874f74846f2e9",
|
|
27
|
+
"outputIndex" : 0,
|
|
28
|
+
"address" : "mgJT8iegL4f9NCgQFeFyfvnSw1Yj4M5Woi",
|
|
29
|
+
"script" : "76a914089acaba6af8b2b4fb4bed3b747ab1e4e60b496588ac",
|
|
30
|
+
"satoshis" : 70000
|
|
31
|
+
});
|
|
32
|
+
```
|