codenlighten/scrypt
0
1---2sidebar_position: 13---4# The BSV submodule5 6sCrypt exports a submodule named `bsv` which is an interface that helps you manage low-level things for the Bitcoin blockchain, such as creating key pairs, building, signing and serializing Bitcoin transactions and more.7 8In the context of sCrypt, it is mainly used for managing key pairs and defining custom transaction builders, as demonstrated in [this section](../how-to-deploy-and-call-a-contract/how-to-customize-a-contract-tx.md).9 10The goal of this section is to guide you through the basics of using the `bsv` submodule.11 12## Importing13 14You can import the `bsv` submodule like so:15 16```ts17import { bsv } from 'scrypt-ts'18```19 20## Private Keys21 22A private key object is essentially just a wrapper around a 256-bit integer.23 24You can generate a Bitcoin private key from a random value:25 26```ts27const privKey = bsv.PrivateKey.fromRandom()28// Same as: const privKey = bsv.PrivateKey.fromRandom(bsv.Network.mainnet)29```30 31This will generate a private key for the Bitcoin main network. To create a key for the test network (also referred to as "testnet"), do the following instead:32 33```ts34const privKey = bsv.PrivateKey.fromRandom(bsv.Networks.testnet)35```36 37The main difference between a mainnet and a testnet key is how they get serialized. Check out [this page](https://wiki.bitcoinsv.io/index.php/Wallet_Import_Format_(WIF)) which explains this in detail.38 39You can also create key object from serialized keys:40```ts41const privKey = bsv.PrivateKey.fromWIF('cVDFHtcTU1wn92AkvTyDbtVqyUJ1SFQTEEanAWJ288xvA7TEPDcZ')42const privKey2 = bsv.PrivateKey.fromString('e3a9863f4c43576cdc316986ba0343826c1e0140b0156263ba6f464260456fe8')43```44 45You can see the decimal value of the private key the following way:46```ts47console.log(privKey.bn.toString())48```49 50> **Warning**51> Private keys should be carefully stored and never be publicly revealed. Otherwise it may lead to loss of funds.52 53## Public Keys54 55A public key is a key that is derived from a private key and can be shared publicly. Mathematically, a public key is a point on the default elliptic curve that Bitcoin uses, named [`SECP256K1`](https://wiki.bitcoinsv.io/index.php/Secp256k1). It is the curve's base point multiplied by the value of the private key.56 57You can get the public key corresponding to a private key the following way:58 59```ts60const privKey = bsv.PrivateKey.fromRandom(bsv.Networks.testnet)61const pubKey = privKey.toPublicKey()62```63 64Same as with private key you can serialize and deserialize public keys:65 66```ts67const pubKey = bsv.PublicKey.fromHex('03a687b08533e37d5a6ff5c8b54a9869d4def9bdc2a4bf8c3a5b3b34d8934ccd17')68 69console.log(pubKey.toHex())70// 03a687b08533e37d5a6ff5c8b54a9869d4def9bdc2a4bf8c3a5b3b34d8934ccd1771```72 73## Addresses74 75You can get a Bitcoin address from either the private key or the public key:76 77```ts78const privKey = bsv.PrivateKey.fromRandom(bsv.Networks.testnet)79const pubKey = privKey.toPublicKey()80 81console.log(privKey.toAddress())82// mxRjX2uxHHmS4rdSYcmCcp2G91eseb5PpF83console.log(pubKey.toAddress())84// mxRjX2uxHHmS4rdSYcmCcp2G91eseb5PpF85```86 87Read [this wiki page](https://wiki.bitcoinsv.io/index.php/Bitcoin_address) for more information on how Bitcoin addresses get constructed.88 89## Hash Functions90 91The `bsv` submodule offers various hash functions that are commonly used in Bitcoin. You can use them like so:92 93```ts94const hashString = bsv.crypto.Hash.sha256(Buffer.from('this is the data I want to hash')).toString('hex')95console.log(hashString)96// f88eec7ecabf88f9a64c4100cac1e0c0c4581100492137d1b656ea626cad63e397```98 99The hash functions available in the `bsv` submodule are:100 101| Hash Function | Output Length | Description |102|---------------|--------------|------------------------------------------------------------|103| sha256 | 32 bytes | The SHA256 hash. |104| sha256sha256 | 32 bytes | The SHA256 hash of the SHA256 hash. Used for blocks and transactions. |105| sha512 | 64 bytes | The SHA512 hash. Commonly used in applications. |106| sha1 | 20 bytes | The SHA1 hash. |107| ripemd160 | 20 bytes | The RIPEMD160 hash. |108| sha256ripemd160 | 20 bytes | The RIPEMD160 hash of the SHA256 hash. Used in Bitcoin addresses. |109 110Note however, that these [bsv.js hash functions](https://github.com/moneybutton/bsv/blob/master/lib/hash.js) should not be confused with [sCrypt's native hash functions](https://scrypt.io/docs/reference/#hashing-functions). These functions cannot be used in a smart contract method.111 112## Constructing Transactions113 114The `bsv` submodule offers a flexible system for constructing Bitcoin transactions. Users are able to define scripts, transaction inputs and outputs, and a whole transaction including its metadata. For a complete description of Bitcoins transaction format, please read [this wiki page](https://wiki.bitcoinsv.io/index.php/Bitcoin_Transactions).115 116As an exercise let's construct a simple [P2PKH](https://wiki.bitcoinsv.io/index.php/Bitcoin_Transactions#Pay_to_Public_Key_Hash_.28P2PKH.29) transaction from scratch and sign it.117 118> **Note:**119> As you will notice further in these docs, most of these steps won't be needed in a regular smart contract development workflow as sCrypt already does a lot of heavy lifting for you. This section serves more as a deeper look on what is happening under the hood.120 121You can create an empty transaction like this:122```ts123let tx = new bsv.Transaction()124```125 126Because the transaction will need an input that provides it with some funds, we can use the `from` function to add one that unlocks the specified [UTXO](https://wiki.bitcoinsv.io/index.php/UTXO):127 128```ts129let tx = new bsv.Transaction()130 .from({131 // TXID that contains the output you want to unlock:132 txId: 'f50b8c6dedea6a4371d17040a9e8d2ea73d369177737fb9f47177fbda7d4d387',133 // Index of the UTXO:134 outputIndex: 0,135 // Script of the UTXO. In this case it's a regular P2PKH script:136 script: bsv.Script.fromASM('OP_DUP OP_HASH160 fde69facc20be6eee5ebf5f0ae96444106a0053f OP_EQUALVERIFY OP_CHECKSIG').toHex(),137 // Value locked in the UTXO in satoshis:138 satoshis: 99904139 })140```141 142Now, the transaction needs an output that will pay to the address `mxXPxaRvFE3178Cr6KK7nrQ76gxjvBQ4UQ` in our example:143 144```ts145let tx = new bsv.Transaction()146 .from({147 // TXID that contains the output you want to unlock:148 txId: 'f50b8c6dedea6a4371d17040a9e8d2ea73d369177737fb9f47177fbda7d4d387',149 // Index of the UTXO:150 outputIndex: 0,151 // Script of the UTXO. In this case it's a regular P2PKH script:152 script: bsv.Script.fromASM('OP_DUP OP_HASH160 fde69facc20be6eee5ebf5f0ae96444106a0053f OP_EQUALVERIFY OP_CHECKSIG').toHex(),153 // Value locked in the UTXO in satoshis:154 satoshis: 99904155 }).addOutput(156 new bsv.Transaction.Output({157 script: bsv.Script.buildPublicKeyHashOut('mxXPxaRvFE3178Cr6KK7nrQ76gxjvBQ4UQ'),158 satoshis: 99804,159 })160 )161```162 163Notice how the output value is 100 less than the value of the UTXO we're unlocking. This difference is the [transaction fee](https://wiki.bitcoinsv.io/index.php/Transaction_fees) (sometimes also called the miner fee).164 165### Signing166 167OK, now that we have the transaction constructed, it's time to sign it. First, we need to seal the transaction, so it will be ready to sign. Then we call the `sign` function, which takes the private key that can unlock the UTXO we passed to the `from` function. In our example, this is the private key that corresponds to the address `n4fTXc2kaKXHyaxmuH5FTKiJ8Tr4fCPHFy`:168 169```ts170tx = tx.seal().sign('cNSb8V7pRt6r5HrPTETq2Li2EWYEjA7EcQ1E8V2aGdd6UzN9EuMw')171```172 173Viola! Thats it. This will add the necessary data to the transaction's input script. That being the signature along with the public key of our signing key.174 175Now our transaction is ready to be posted to the blockchain. You can serialize the transaction the following way:176 177```ts178console.log(tx.serialize())179```180 181For broadcasting, you can use any provider you like. For demo purposes you can simply paste the serialized transaction [here](https://test.whatsonchain.com/broadcast).182 183### OP_RETURN Scripts184 185In case you would like to put some arbitrary data on-chain, without any locking logic, you can use transaction outputs with an [OP_RETURN](https://wiki.bitcoinsv.io/index.php/OP_RETURN) script.186 187An example of an OP_RETURN script written in ASM format is this:188 189```190OP_FALSE OP_RETURN 734372797074191```192 193In effect, the opcodes `OP_FALSE OP_RETURN` will make the script unspendable. After them we can insert arbitrary chunks of data. The `734372797074` is actually the string `sCrypt` encoded as an `utf-8` hexadecimal string.194 195```js196console.log(Buffer.from('sCrypt').toString('hex'))197// 734372797074198```199 200An OP_RETURN script can also contain more than a single chunk of data:201```202OP_FALSE OP_RETURN 48656c6c6f 66726f6d 734372797074203```204 205The `bsv` submodule offers a convenient function to construct such scripts:206 207```ts208const opRetScript: bsv.Script = bsv.Script.buildSafeDataOut(['Hello', 'from', 'sCrypt'])209```210 211We can add the resulting `bsv.Script` object to an output as we showed [above](#constructing-transactions).212 213 214## References215 216- Take a look at the full [`bsv` submodule reference](../reference/modules/bsv) for a full list of what functions it provides.217- As the `bsv` submodule is based on MoneyButton's library implementation, take a look at their [video tutorial series](https://www.youtube.com/watch?v=bkGiCjYBpJE&list=PLwj1dNv7vWsMrjrWeiQEelbKTI3Lrmvqp&index=1). Although do keep in mind that some things might be slightly different as it's an old series.218 